<commit_before>use core::str::FromStr;

use string::String;

use ffi::CString;

use cell::GlobalCellMutRef;

use hal::xen::store::{Result, Error};

use super::imp::{XenStoreImpl, RequestBuilder, XsdSockmsgType};

/// A transaction with the Xen Store
///
/// Note: the transaction is automatically ended on `Drop` if not already
/// down.
pub struct Transaction<'a> {
    ended: bool,
    tx_id: u32,
    imp: GlobalCellMutRef<'a, XenStoreImpl>,
}

impl<'a> Transaction<'a> {
    #[doc(hidden)]
    pub fn new(mut imp: GlobalCellMutRef<'a, XenStoreImpl>) -> Result<Transaction<'a>> {
        let empty_data = CString::new("").unwrap();

        let tx_req = {
            RequestBuilder::new(0).set_msg_type(XsdSockmsgType::TransactionStart)
                                  .append_data(empty_data.as_bytes_with_nul())
        };

        imp.send(tx_req).and_then(|data| {
            match String::from_utf8(data) {
                Err(..) => Err(Error::Conversion),
                Ok(s) => match u32::from_str(&s[..]) {
                    Err(..) => Err(Error::Conversion),
                    Ok(id) => Ok(Transaction {
                        ended: false,
                        tx_id: id,
                        imp: imp,
                    }),
                },
            }
        })
    }

    /// Read the value pointed by `key`
    pub fn read(&mut self, key: CString) -> Result<String> {
        let req = RequestBuilder::new(self.tx_id).set_msg_type(XsdSockmsgType::Read)
                                                 .append_data(key.as_bytes_with_nul());

        self.imp.send(req).and_then(|data| {
            match String::from_utf8(data) {
                Err(..) => Err(Error::Conversion),
                Ok(s) => Ok(s),
            }
        })
    }

    /// Write the value of `key`
    pub fn write(&mut self, key: CString, value: CString) -> Result<()> {
        let req = {
            RequestBuilder::new(self.tx_id).set_msg_type(XsdSockmsgType::Write)
                                           .append_data(key.as_bytes_with_nul())
                                           .append_data(value.as_bytes())
        };

        self.imp.send(req).map(|_| ())
    }

    fn _end(&mut self, data: CString) -> Result<()> {
        let req = {
            RequestBuilder::new(self.tx_id).set_msg_type(XsdSockmsgType::TransactionEnd)
                                           .append_data(data.as_bytes_with_nul())
        };

        self.imp.send(req).and_then(|data| {
            match String::from_utf8(data) {
                Err(..) => Err(Error::Conversion),
                Ok(s) => {
                    match s.as_ref() {
                        "OK" => {
                            self.ended = true;
                            Ok(())
                        }
                        _ => Err(Error::Unknown),
                    }
                }
            }
        })
    }

    /// End the transaction
    pub fn end(&mut self) -> Result<()> {
        self._end(CString::new("T").unwrap())
    }

    /// Abort the transaction
    pub fn abort(&mut self) -> Result<()> {
        self._end(CString::new("F").unwrap())
    }
}

impl<'a> Drop for Transaction<'a> {
    fn drop(&mut self) {
        if !self.ended {
            self.abort().unwrap();
        }
    }
}
<commit_msg>xen/store: Add Transaction::directory_list()<commit_after>use core::str::FromStr;

use vec::Vec;
use string::String;

use ffi::CString;

use cell::GlobalCellMutRef;

use hal::xen::store::{Result, Error};

use super::imp::{XenStoreImpl, RequestBuilder, XsdSockmsgType};

/// A transaction with the Xen Store
///
/// Note: the transaction is automatically ended on `Drop` if not already
/// down.
pub struct Transaction<'a> {
    ended: bool,
    tx_id: u32,
    imp: GlobalCellMutRef<'a, XenStoreImpl>,
}

impl<'a> Transaction<'a> {
    #[doc(hidden)]
    pub fn new(mut imp: GlobalCellMutRef<'a, XenStoreImpl>) -> Result<Transaction<'a>> {
        let empty_data = CString::new("").unwrap();

        let tx_req = {
            RequestBuilder::new(0).set_msg_type(XsdSockmsgType::TransactionStart)
                                  .append_data(empty_data.as_bytes_with_nul())
        };

        imp.send(tx_req).and_then(|data| {
            match String::from_utf8(data) {
                Err(..) => Err(Error::Conversion),
                Ok(s) => match u32::from_str(&s[..]) {
                    Err(..) => Err(Error::Conversion),
                    Ok(id) => Ok(Transaction {
                        ended: false,
                        tx_id: id,
                        imp: imp,
                    }),
                },
            }
        })
    }

    /// List a directory in the Xen Store
    pub fn directory_list(&mut self, directory: CString) -> Result<Vec<String>> {
        let req = {
            RequestBuilder::new(self.tx_id).set_msg_type(XsdSockmsgType::Directory)
                                           .append_data(directory.as_bytes_with_nul())
        };

        self.imp.send(req).and_then(|data| {
            let mut v = Vec::<String>::new();
            let mut s = String::new();

            for b in data {
                if b == 0 {
                    v.push(s);
                    s = String::new();
                } else {
                    s.push(b as char);
                }
            }

            Ok(v)
        })
    }

    /// Read the value pointed by `key`
    pub fn read(&mut self, key: CString) -> Result<String> {
        let req = RequestBuilder::new(self.tx_id).set_msg_type(XsdSockmsgType::Read)
                                                 .append_data(key.as_bytes_with_nul());

        self.imp.send(req).and_then(|data| {
            match String::from_utf8(data) {
                Err(..) => Err(Error::Conversion),
                Ok(s) => Ok(s),
            }
        })
    }

    /// Write the value of `key`
    pub fn write(&mut self, key: CString, value: CString) -> Result<()> {
        let req = {
            RequestBuilder::new(self.tx_id).set_msg_type(XsdSockmsgType::Write)
                                           .append_data(key.as_bytes_with_nul())
                                           .append_data(value.as_bytes())
        };

        self.imp.send(req).map(|_| ())
    }

    fn _end(&mut self, data: CString) -> Result<()> {
        let req = {
            RequestBuilder::new(self.tx_id).set_msg_type(XsdSockmsgType::TransactionEnd)
                                           .append_data(data.as_bytes_with_nul())
        };

        self.imp.send(req).and_then(|data| {
            match String::from_utf8(data) {
                Err(..) => Err(Error::Conversion),
                Ok(s) => {
                    match s.as_ref() {
                        "OK" => {
                            self.ended = true;
                            Ok(())
                        }
                        _ => Err(Error::Unknown),
                    }
                }
            }
        })
    }

    /// End the transaction
    pub fn end(&mut self) -> Result<()> {
        self._end(CString::new("T").unwrap())
    }

    /// Abort the transaction
    pub fn abort(&mut self) -> Result<()> {
        self._end(CString::new("F").unwrap())
    }
}

impl<'a> Drop for Transaction<'a> {
    fn drop(&mut self) {
        if !self.ended {
            self.abort().unwrap();
        }
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate octavo;

use octavo::digest::prelude::*;
use std::collections::VecDeque;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Point {
    x: usize,
    y: usize,
}

impl Point {
    fn new(x: usize, y: usize) -> Self {
        Point { x: x, y: y }
    }
    fn make_move(&self, mov: Move) -> Point {
        use Move::*;
        match mov {
            Up => {
                Point {
                    x: self.x,
                    y: self.y - 1,
                }
            }
            Down => {
                Point {
                    x: self.x,
                    y: self.y + 1,
                }
            }
            Left => {
                Point {
                    x: self.x - 1,
                    y: self.y,
                }
            }
            Right => {
                Point {
                    x: self.x + 1,
                    y: self.y,
                }
            }
        }
    }
}

impl std::fmt::Display for Point {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(f, "({}, {})", self.x, self.y)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Move {
    Up,
    Down,
    Left,
    Right,
}

impl Move {
    fn as_char(&self) -> char {
        use Move::*;
        match *self {
            Up => 'U',
            Down => 'D',
            Left => 'L',
            Right => 'R',
        }
    }
    fn hits_wall(&self, pos: Point) -> bool {
        use Move::*;
        match *self {
            Up => pos.y == 0,
            Down => pos.y == 3,
            Left => pos.x == 0,
            Right => pos.x == 3,
        }
    }
}

fn md5(input: &[u8]) -> String {
    use std::fmt::Write;
    let mut output_buf = vec![0u8; Md5::output_bytes()];
    let mut digest = Md5::default();
    digest.update(input);
    digest.result(&mut output_buf);
    let mut output = String::with_capacity(output_buf.len() * 2);
    for ch in output_buf {
        write!(output, "{:02x}", ch).expect("could not write to output_buf");
    }
    output
}

fn possible_moves(pos: Point, history: &[Move], key: &str) -> Vec<Move> {
    use Move::*;
    let mut hash_input = key.to_owned();
    hash_input.extend(history.iter().map(|mov| mov.as_char()));
    let hash = md5(hash_input.as_bytes());
    let mut possibilities = Vec::new();
    for (dir, ch) in [Up, Down, Left, Right].into_iter().zip(hash.chars()) {
        match ch {
            'b'...'f' => {
                if !dir.hits_wall(pos) {
                    possibilities.push(*dir);
                }
            }
            _ => continue,
        }
    }
    possibilities
}

fn shortest_path(start: Point, end: Point, key: &str) -> Option<Vec<Move>> {
    let mut move_queue = VecDeque::new();
    move_queue.push_back((start, Vec::new()));
    while let Some((pos, moves)) = move_queue.pop_front() {
        for mov in possible_moves(pos, &moves, key) {
            let mut new_moves = moves.clone();
            new_moves.push(mov);
            let new_pos = pos.make_move(mov);
            if new_pos == end {
                return Some(new_moves);
            }
            move_queue.push_back((new_pos, new_moves));
        }
    }
    None
}

fn parse_args() -> String {
    let matches = clap::App::new("Day 17")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("key")
            .index(1)
            .help("key for generating puzzle")
            .required(true)
            .takes_value(true))
        .get_matches();
    matches.value_of("key").unwrap().to_owned()
}

fn main() {
    let key = parse_args();
    println!("part 1 path:");
    match shortest_path(Point::new(0, 0), Point::new(3, 3), &key) {
        Some(path) => {
            for mov in &path {
                print!("{}", mov.as_char());
            }
            println!();
        }
        None => println!("No path found!"),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    const START: Point = Point { x: 0, y: 0 };
    const END: Point = Point { x: 3, y: 3 };

    fn read_moves(s: &str) -> Vec<Move> {
        use Move::*;
        let mut moves = Vec::with_capacity(s.len());
        for ch in s.chars() {
            match ch {
                'U' => moves.push(Up),
                'D' => moves.push(Down),
                'L' => moves.push(Left),
                'R' => moves.push(Right),
                _ => panic!("bad char: {}", ch),
            }
        }
        moves
    }

    #[test]
    fn example_dead_end() {
        assert_eq!(shortest_path(START, END, "hijkl"), None);
    }

    #[test]
    fn example1() {
        assert_eq!(shortest_path(START, END, "ihgpwlah"),
                   Some(read_moves("DDRRRD")));
    }

    #[test]
    fn example2() {
        assert_eq!(shortest_path(START, END, "kglvqrro"),
                   Some(read_moves("DDUDRLRRUDRD")));
    }

    #[test]
    fn example3() {
        assert_eq!(shortest_path(START, END, "ulqzkmiv"),
                   Some(read_moves("DRURDRUDDLLDLUURRDULRLDUUDDDRR")));
    }
}
<commit_msg>Day 17 part 2<commit_after>extern crate clap;
extern crate octavo;

use octavo::digest::prelude::*;
use std::collections::VecDeque;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Point {
    x: usize,
    y: usize,
}

impl Point {
    fn new(x: usize, y: usize) -> Self {
        Point { x: x, y: y }
    }
    fn make_move(&self, mov: Move) -> Point {
        use Move::*;
        match mov {
            Up => {
                Point {
                    x: self.x,
                    y: self.y - 1,
                }
            }
            Down => {
                Point {
                    x: self.x,
                    y: self.y + 1,
                }
            }
            Left => {
                Point {
                    x: self.x - 1,
                    y: self.y,
                }
            }
            Right => {
                Point {
                    x: self.x + 1,
                    y: self.y,
                }
            }
        }
    }
}

impl std::fmt::Display for Point {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(f, "({}, {})", self.x, self.y)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
enum Move {
    Up,
    Down,
    Left,
    Right,
}

impl Move {
    fn as_char(&self) -> char {
        use Move::*;
        match *self {
            Up => 'U',
            Down => 'D',
            Left => 'L',
            Right => 'R',
        }
    }
    fn hits_wall(&self, pos: Point) -> bool {
        use Move::*;
        match *self {
            Up => pos.y == 0,
            Down => pos.y == 3,
            Left => pos.x == 0,
            Right => pos.x == 3,
        }
    }
}

fn md5(input: &[u8]) -> String {
    use std::fmt::Write;
    let mut output_buf = vec![0u8; Md5::output_bytes()];
    let mut digest = Md5::default();
    digest.update(input);
    digest.result(&mut output_buf);
    let mut output = String::with_capacity(output_buf.len() * 2);
    for ch in output_buf {
        write!(output, "{:02x}", ch).expect("could not write to output_buf");
    }
    output
}

fn possible_moves(pos: Point, history: &[Move], key: &str) -> Vec<Move> {
    use Move::*;
    let mut hash_input = key.to_owned();
    hash_input.extend(history.iter().map(|mov| mov.as_char()));
    let hash = md5(hash_input.as_bytes());
    let mut possibilities = Vec::new();
    for (dir, ch) in [Up, Down, Left, Right].into_iter().zip(hash.chars()) {
        match ch {
            'b'...'f' => {
                if !dir.hits_wall(pos) {
                    possibilities.push(*dir);
                }
            }
            _ => continue,
        }
    }
    possibilities
}

fn shortest_path(start: Point, end: Point, key: &str) -> Option<Vec<Move>> {
    let mut move_queue = VecDeque::new();
    move_queue.push_back((start, Vec::new()));
    while let Some((pos, moves)) = move_queue.pop_front() {
        for mov in possible_moves(pos, &moves, key) {
            let mut new_moves = moves.clone();
            new_moves.push(mov);
            let new_pos = pos.make_move(mov);
            if new_pos == end {
                return Some(new_moves);
            }
            move_queue.push_back((new_pos, new_moves));
        }
    }
    None
}

fn longest_path(start: Point, end: Point, key: &str) -> Option<Vec<Move>> {
    let mut move_queue = VecDeque::new();
    move_queue.push_back((start, Vec::new()));
    let mut successful_paths = Vec::new();
    while let Some((pos, moves)) = move_queue.pop_front() {
        for mov in possible_moves(pos, &moves, key) {
            let mut new_moves = moves.clone();
            new_moves.push(mov);
            let new_pos = pos.make_move(mov);
            if new_pos == end {
                successful_paths.push(new_moves);
            } else {
                move_queue.push_back((new_pos, new_moves));
            }
        }
    }
    successful_paths.sort_by_key(|path| path.len());
    successful_paths.pop()
}

fn parse_args() -> String {
    let matches = clap::App::new("Day 17")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("key")
            .index(1)
            .help("key for generating puzzle")
            .required(true)
            .takes_value(true))
        .get_matches();
    matches.value_of("key").unwrap().to_owned()
}

fn main() {
    let key = parse_args();
    println!("shortest path:");
    match shortest_path(Point::new(0, 0), Point::new(3, 3), &key) {
        Some(path) => {
            for mov in &path {
                print!("{}", mov.as_char());
            }
            println!();
        }
        None => println!("No path found!"),
    }
    println!("longest path:");
    match longest_path(Point::new(0, 0), Point::new(3, 3), &key) {
        Some(path) => {
            for mov in &path {
                print!("{}", mov.as_char());
            }
            println!();
            println!("length: {}", path.len());
        }
        None => println!("No path found!"),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    const START: Point = Point { x: 0, y: 0 };
    const END: Point = Point { x: 3, y: 3 };

    fn read_moves(s: &str) -> Vec<Move> {
        use Move::*;
        let mut moves = Vec::with_capacity(s.len());
        for ch in s.chars() {
            match ch {
                'U' => moves.push(Up),
                'D' => moves.push(Down),
                'L' => moves.push(Left),
                'R' => moves.push(Right),
                _ => panic!("bad char: {}", ch),
            }
        }
        moves
    }

    #[test]
    fn example_dead_end() {
        assert_eq!(shortest_path(START, END, "hijkl"), None);
    }

    #[test]
    fn short_path_example_1() {
        assert_eq!(shortest_path(START, END, "ihgpwlah"),
                   Some(read_moves("DDRRRD")));
    }

    #[test]
    fn short_path_example_2() {
        assert_eq!(shortest_path(START, END, "kglvqrro"),
                   Some(read_moves("DDUDRLRRUDRD")));
    }

    #[test]
    fn short_path_example_3() {
        assert_eq!(shortest_path(START, END, "ulqzkmiv"),
                   Some(read_moves("DRURDRUDDLLDLUURRDULRLDUUDDDRR")));
    }

    #[test]
    fn long_path_example_1() {
        assert_eq!(longest_path(START, END, "ihgpwlah").unwrap().len(), 370);
    }

    #[test]
    fn long_path_example_2() {
        assert_eq!(longest_path(START, END, "kglvqrro").unwrap().len(), 492);
    }

    #[test]
    fn long_path_example_3() {
        assert_eq!(longest_path(START, END, "ulqzkmiv").unwrap().len(), 830);
    }
}
<|endoftext|>


<commit_before>//! Provides types and functions related to working with PostgreSQL
//!
//! Much of this module is re-exported from database agnostic locations.
//! However, if you are writing code specifically to extend Diesel on
//! PostgreSQL, you may need to work with this module directly.

pub mod expression;
pub mod types;

#[doc(hidden)]
#[cfg(feature = "with-deprecated")]
#[deprecated(since = "2.0.0", note = "Use `diesel::upsert` instead")]
pub use crate::upsert;

mod backend;
mod connection;
mod metadata_lookup;
pub(crate) mod query_builder;
pub(crate) mod serialize;
mod transaction;
mod value;

pub use self::backend::{Pg, PgTypeMetadata};
pub use self::connection::PgConnection;
pub use self::metadata_lookup::PgMetadataLookup;
pub use self::query_builder::DistinctOnClause;
pub use self::query_builder::PgQueryBuilder;
pub use self::transaction::TransactionBuilder;
pub use self::value::PgValue;

/// Data structures for PG types which have no corresponding Rust type
///
/// Most of these types are used to implement `ToSql` and `FromSql` for higher
/// level types.
pub mod data_types {
    #[doc(inline)]
    pub use super::types::date_and_time::{PgDate, PgInterval, PgTime, PgTimestamp};
    #[doc(inline)]
    pub use super::types::floats::PgNumeric;
    #[doc(inline)]
    pub use super::types::money::PgMoney;
    pub use super::types::money::PgMoney as Cents;
}
<commit_msg>Move reexport to the other reexports<commit_after>//! Provides types and functions related to working with PostgreSQL
//!
//! Much of this module is re-exported from database agnostic locations.
//! However, if you are writing code specifically to extend Diesel on
//! PostgreSQL, you may need to work with this module directly.

pub mod expression;
pub mod types;

mod backend;
mod connection;
mod metadata_lookup;
pub(crate) mod query_builder;
pub(crate) mod serialize;
mod transaction;
mod value;

pub use self::backend::{Pg, PgTypeMetadata};
pub use self::connection::PgConnection;
pub use self::metadata_lookup::PgMetadataLookup;
pub use self::query_builder::DistinctOnClause;
pub use self::query_builder::PgQueryBuilder;
pub use self::transaction::TransactionBuilder;
pub use self::value::PgValue;
#[doc(hidden)]
#[cfg(feature = "with-deprecated")]
#[deprecated(since = "2.0.0", note = "Use `diesel::upsert` instead")]
pub use crate::upsert;

/// Data structures for PG types which have no corresponding Rust type
///
/// Most of these types are used to implement `ToSql` and `FromSql` for higher
/// level types.
pub mod data_types {
    #[doc(inline)]
    pub use super::types::date_and_time::{PgDate, PgInterval, PgTime, PgTimestamp};
    #[doc(inline)]
    pub use super::types::floats::PgNumeric;
    #[doc(inline)]
    pub use super::types::money::PgMoney;
    pub use super::types::money::PgMoney as Cents;
}
<|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 std::str::FromStr;
use app_units::Au;
use euclid::TypedSize2D;

use yaml_rust::Yaml;

use webrender_traits::*;

pub trait YamlHelper {
    fn as_force_f32(&self) -> Option<f32>;
    fn as_vec_f32(&self) -> Option<Vec<f32>>;
    fn as_vec_u32(&self) -> Option<Vec<u32>>;
    fn as_rect(&self) -> Option<LayoutRect>;
    fn as_size(&self) -> Option<LayoutSize>;
    fn as_point(&self) -> Option<LayoutPoint>;
    fn as_matrix4d(&self) -> Option<LayoutTransform>;
    fn as_colorf(&self) -> Option<ColorF>;
    fn as_vec_colorf(&self) -> Option<Vec<ColorF>>;
    fn as_px_to_au(&self) -> Option<Au>;
    fn as_pt_to_au(&self) -> Option<Au>;
    fn as_vec_string(&self) -> Option<Vec<String>>;
    fn as_border_radius(&self) -> Option<BorderRadius>;
}

fn string_to_color(color: &str) -> Option<ColorF> {
    match color {
        "red" => Some(ColorF::new(1.0, 0.0, 0.0, 1.0)),
        "green" => Some(ColorF::new(0.0, 1.0, 0.0, 1.0)),
        "blue" => Some(ColorF::new(0.0, 0.0, 1.0, 1.0)),
        "white" => Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
        "black" => Some(ColorF::new(0.0, 0.0, 0.0, 1.0)),
        s => {
            let items: Vec<f32> = s.split_whitespace().map(|s| f32::from_str(s).unwrap()).collect();
            if items.len() == 3 {
                Some(ColorF::new(items[0] / 255.0, items[1] / 255.0, items[2] / 255.0, 1.0))
            } else if items.len() == 4 {
                Some(ColorF::new(items[0] / 255.0, items[1] / 255.0, items[2] / 255.0, items[3]))
            } else {
                None
            }
        }
    }
}

impl YamlHelper for Yaml {
    fn as_force_f32(&self) -> Option<f32> {
        match *self {
            Yaml::Integer(iv) => Some(iv as f32),
            Yaml::String(ref sv) | Yaml::Real(ref sv) => match f32::from_str(sv.as_str()) {
                Ok(v) => Some(v),
                Err(_) => None
            },
            _ => None
        }
    }

    fn as_vec_f32(&self) -> Option<Vec<f32>> {
        match *self {
            Yaml::String(ref s) | Yaml::Real(ref s) => {
                s.split_whitespace()
                 .map(|v| f32::from_str(v))
                 .collect::<Result<Vec<_>,_>>()
                 .ok()
            }
            Yaml::Array(ref v) => {
                v.iter().map(|v| {
                    match *v {
                        Yaml::Integer(k) => Ok(k as f32),
                        Yaml::String(ref k) | Yaml::Real(ref k) => {
                            f32::from_str(&k).map_err(|_| false)
                        },
                        _ => Err(false),
                    }
                }).collect::<Result<Vec<_>,_>>().ok()
            }
            Yaml::Integer(k) => {
                Some(vec![k as f32])
            }
            _ => None
        }
    }

    fn as_vec_u32(&self) -> Option<Vec<u32>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_i64().unwrap() as u32).collect())
        } else {
            None
        }
    }

    fn as_px_to_au(&self) -> Option<Au> {
        match self.as_force_f32() {
            Some(fv) => Some(Au::from_f32_px(fv)),
            None => None
        }
    }

    fn as_pt_to_au(&self) -> Option<Au> {
        match self.as_force_f32() {
            Some(fv) => Some(Au::from_f32_px(fv * 16. / 12.)),
            None => None
        }
    }

    fn as_rect(&self) -> Option<LayoutRect> {
        if self.is_badvalue() {
            return None;
        }

        if let Some(nums) = self.as_vec_f32() {
            if nums.len() == 4 {
                return Some(LayoutRect::new(LayoutPoint::new(nums[0], nums[1]), LayoutSize::new(nums[2], nums[3])));
            }
        }

        None
    }

    fn as_size(&self) -> Option<LayoutSize> {
        if self.is_badvalue() {
            return None;
        }

        let nums = self.as_vec_f32().unwrap();
        if nums.len() != 2 {
            panic!("size expected 2 float values, got {} instead ('{:?}')", nums.len(), self);
        }
        Some(LayoutSize::new(nums[0], nums[1]))
    }

    fn as_point(&self) -> Option<LayoutPoint> {
        if self.is_badvalue() {
            return None;
        }

        let nums = self.as_vec_f32().unwrap();
        if nums.len() != 2 {
            panic!("point expected 2 float values, got {} instead ('{:?}')", nums.len(), self);
        }
        Some(LayoutPoint::new(nums[0], nums[1]))
    }

    fn as_matrix4d(&self) -> Option<LayoutTransform> {
        None
    }

    fn as_colorf(&self) -> Option<ColorF> {
        if let Some(mut nums) = self.as_vec_f32() {
            if nums.len() != 3 && nums.len() != 4 {
                panic!("color expected a color name, or 3-4 floats; got '{:?}'", self);
            }

            if nums.len() == 3 {
                nums.push(1.0);
            }
            return Some(ColorF::new(nums[0] / 255.0, nums[1] / 255.0, nums[2] / 255.0, nums[3]));
        }

        if let Some(s) = self.as_str() {
            string_to_color(s)
        } else {
            None
        }
    }

    fn as_vec_colorf(&self) -> Option<Vec<ColorF>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_colorf().unwrap()).collect())
        } else {
            if let Some(color) = self.as_colorf() {
                Some(vec![color])
            } else {
                None
            }
        }
    }

    fn as_vec_string(&self) -> Option<Vec<String>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_str().unwrap().to_owned()).collect())
        } else if let Some(s) = self.as_str() {
            Some(vec![s.to_owned()])
        } else {
            None
        }
    }

    fn as_border_radius(&self) -> Option<BorderRadius> {
        match *self {
            Yaml::BadValue => { None }
            Yaml::String(ref s) | Yaml::Real(ref s) => {
                let fv = f32::from_str(s).unwrap();
                Some(BorderRadius::uniform(fv))
            }
            Yaml::Integer(v) => {
                Some(BorderRadius::uniform(v as f32))
            }
            Yaml::Hash(_) => {
                let top_left = self["top_left"].as_size().unwrap_or(TypedSize2D::zero());
                let top_right = self["top_right"].as_size().unwrap_or(TypedSize2D::zero());
                let bottom_left = self["bottom_left"].as_size().unwrap_or(TypedSize2D::zero());
                let bottom_right = self["bottom_right"].as_size().unwrap_or(TypedSize2D::zero());
                Some(BorderRadius {
                    top_left: top_left,
                    top_right: top_right,
                    bottom_left: bottom_left,
                    bottom_right: bottom_right,
                })
            }
            _ => {
                panic!("Invalid border radius specified: {:?}", self);
            }
        }
    }
}
<commit_msg>Add a reader for LayoutTransform.<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 std::str::FromStr;
use app_units::Au;
use euclid::TypedSize2D;

use yaml_rust::Yaml;

use webrender_traits::*;

pub trait YamlHelper {
    fn as_force_f32(&self) -> Option<f32>;
    fn as_vec_f32(&self) -> Option<Vec<f32>>;
    fn as_vec_u32(&self) -> Option<Vec<u32>>;
    fn as_rect(&self) -> Option<LayoutRect>;
    fn as_size(&self) -> Option<LayoutSize>;
    fn as_point(&self) -> Option<LayoutPoint>;
    fn as_matrix4d(&self) -> Option<LayoutTransform>;
    fn as_colorf(&self) -> Option<ColorF>;
    fn as_vec_colorf(&self) -> Option<Vec<ColorF>>;
    fn as_px_to_au(&self) -> Option<Au>;
    fn as_pt_to_au(&self) -> Option<Au>;
    fn as_vec_string(&self) -> Option<Vec<String>>;
    fn as_border_radius(&self) -> Option<BorderRadius>;
}

fn string_to_color(color: &str) -> Option<ColorF> {
    match color {
        "red" => Some(ColorF::new(1.0, 0.0, 0.0, 1.0)),
        "green" => Some(ColorF::new(0.0, 1.0, 0.0, 1.0)),
        "blue" => Some(ColorF::new(0.0, 0.0, 1.0, 1.0)),
        "white" => Some(ColorF::new(1.0, 1.0, 1.0, 1.0)),
        "black" => Some(ColorF::new(0.0, 0.0, 0.0, 1.0)),
        s => {
            let items: Vec<f32> = s.split_whitespace().map(|s| f32::from_str(s).unwrap()).collect();
            if items.len() == 3 {
                Some(ColorF::new(items[0] / 255.0, items[1] / 255.0, items[2] / 255.0, 1.0))
            } else if items.len() == 4 {
                Some(ColorF::new(items[0] / 255.0, items[1] / 255.0, items[2] / 255.0, items[3]))
            } else {
                None
            }
        }
    }
}

impl YamlHelper for Yaml {
    fn as_force_f32(&self) -> Option<f32> {
        match *self {
            Yaml::Integer(iv) => Some(iv as f32),
            Yaml::String(ref sv) | Yaml::Real(ref sv) => match f32::from_str(sv.as_str()) {
                Ok(v) => Some(v),
                Err(_) => None
            },
            _ => None
        }
    }

    fn as_vec_f32(&self) -> Option<Vec<f32>> {
        match *self {
            Yaml::String(ref s) | Yaml::Real(ref s) => {
                s.split_whitespace()
                 .map(|v| f32::from_str(v))
                 .collect::<Result<Vec<_>,_>>()
                 .ok()
            }
            Yaml::Array(ref v) => {
                v.iter().map(|v| {
                    match *v {
                        Yaml::Integer(k) => Ok(k as f32),
                        Yaml::String(ref k) | Yaml::Real(ref k) => {
                            f32::from_str(&k).map_err(|_| false)
                        },
                        _ => Err(false),
                    }
                }).collect::<Result<Vec<_>,_>>().ok()
            }
            Yaml::Integer(k) => {
                Some(vec![k as f32])
            }
            _ => None
        }
    }

    fn as_vec_u32(&self) -> Option<Vec<u32>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_i64().unwrap() as u32).collect())
        } else {
            None
        }
    }

    fn as_px_to_au(&self) -> Option<Au> {
        match self.as_force_f32() {
            Some(fv) => Some(Au::from_f32_px(fv)),
            None => None
        }
    }

    fn as_pt_to_au(&self) -> Option<Au> {
        match self.as_force_f32() {
            Some(fv) => Some(Au::from_f32_px(fv * 16. / 12.)),
            None => None
        }
    }

    fn as_rect(&self) -> Option<LayoutRect> {
        if self.is_badvalue() {
            return None;
        }

        if let Some(nums) = self.as_vec_f32() {
            if nums.len() == 4 {
                return Some(LayoutRect::new(LayoutPoint::new(nums[0], nums[1]), LayoutSize::new(nums[2], nums[3])));
            }
        }

        None
    }

    fn as_size(&self) -> Option<LayoutSize> {
        if self.is_badvalue() {
            return None;
        }

        let nums = self.as_vec_f32().unwrap();
        if nums.len() != 2 {
            panic!("size expected 2 float values, got {} instead ('{:?}')", nums.len(), self);
        }
        Some(LayoutSize::new(nums[0], nums[1]))
    }

    fn as_point(&self) -> Option<LayoutPoint> {
        if self.is_badvalue() {
            return None;
        }

        let nums = self.as_vec_f32().unwrap();
        if nums.len() != 2 {
            panic!("point expected 2 float values, got {} instead ('{:?}')", nums.len(), self);
        }
        Some(LayoutPoint::new(nums[0], nums[1]))
    }

    fn as_matrix4d(&self) -> Option<LayoutTransform> {
        if let Some(mut nums) = self.as_vec_f32() {
            if nums.len() != 16 {
                panic!("expected 16 floats, got '{:?}'", self);
            }
            return Some(LayoutTransform::row_major(nums[0], nums[1], nums[2], nums[3],
                                                   nums[4], nums[5], nums[6], nums[7],
                                                   nums[8], nums[9], nums[10], nums[11],
                                                   nums[12], nums[13], nums[14], nums[15]))
        }
        None
    }

    fn as_colorf(&self) -> Option<ColorF> {
        if let Some(mut nums) = self.as_vec_f32() {
            if nums.len() != 3 && nums.len() != 4 {
                panic!("color expected a color name, or 3-4 floats; got '{:?}'", self);
            }

            if nums.len() == 3 {
                nums.push(1.0);
            }
            return Some(ColorF::new(nums[0] / 255.0, nums[1] / 255.0, nums[2] / 255.0, nums[3]));
        }

        if let Some(s) = self.as_str() {
            string_to_color(s)
        } else {
            None
        }
    }

    fn as_vec_colorf(&self) -> Option<Vec<ColorF>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_colorf().unwrap()).collect())
        } else {
            if let Some(color) = self.as_colorf() {
                Some(vec![color])
            } else {
                None
            }
        }
    }

    fn as_vec_string(&self) -> Option<Vec<String>> {
        if let Some(v) = self.as_vec() {
            Some(v.iter().map(|v| v.as_str().unwrap().to_owned()).collect())
        } else if let Some(s) = self.as_str() {
            Some(vec![s.to_owned()])
        } else {
            None
        }
    }

    fn as_border_radius(&self) -> Option<BorderRadius> {
        match *self {
            Yaml::BadValue => { None }
            Yaml::String(ref s) | Yaml::Real(ref s) => {
                let fv = f32::from_str(s).unwrap();
                Some(BorderRadius::uniform(fv))
            }
            Yaml::Integer(v) => {
                Some(BorderRadius::uniform(v as f32))
            }
            Yaml::Hash(_) => {
                let top_left = self["top_left"].as_size().unwrap_or(TypedSize2D::zero());
                let top_right = self["top_right"].as_size().unwrap_or(TypedSize2D::zero());
                let bottom_left = self["bottom_left"].as_size().unwrap_or(TypedSize2D::zero());
                let bottom_right = self["bottom_right"].as_size().unwrap_or(TypedSize2D::zero());
                Some(BorderRadius {
                    top_left: top_left,
                    top_right: top_right,
                    bottom_left: bottom_left,
                    bottom_right: bottom_right,
                })
            }
            _ => {
                panic!("Invalid border radius specified: {:?}", self);
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>feat(doc): Fix positions of indices<commit_after><|endoftext|>


<commit_before><commit_msg>Apply suggestions from code review<commit_after><|endoftext|>


<commit_before>use analysis;
use analysis::rust_type::rust_type;
use analysis::type_kind::TypeKind;
use env::Env;
use library;
use traits::*;

pub trait TranslateFromGlib {
    fn translate_from_glib_as_function(&self, env: &Env,
        func: &analysis::functions::Info) -> (String, String);
}

impl TranslateFromGlib for library::Parameter {
    fn translate_from_glib_as_function(&self,
        env: &Env, func: &analysis::functions::Info) -> (String, String) {
        let kind = TypeKind::of(&env.library, self.typ);
        if func.kind == library::FunctionKind::Constructor {
            let rust_type = rust_type(env, self.typ);
            if rust_type.as_str() != func.class_name.as_str() {
                let from_glib_xxx = from_glib_xxx(self.transfer);
                (
                    format!("{}::{}", rust_type.as_str(), from_glib_xxx.0),
                    format!("{}.downcast_unchecked()",from_glib_xxx.1)
                )
            } else {
                ("TODO:constructors_body ".into(), String::new())
            }
        } else {
            match kind {
                TypeKind::Converted => ("from_glib(".into(), ")".into()),
                TypeKind::Direct |
                    TypeKind::Enumeration => (String::new(), String::new()),
                //TODO: check gtk_dialog_get_content_area <type name="Box" c:type="GtkWidget*"/>
                TypeKind::Object => from_glib_xxx(self.transfer),
                _ => (format!("TODO {:?}:", kind), String::new()),
            }
        }
    }
}

impl TranslateFromGlib for Option<library::Parameter> {
    fn translate_from_glib_as_function(&self, env: &Env,
        func: &analysis::functions::Info) -> (String, String) {
        match self {
            &Some(ref par) => par.translate_from_glib_as_function(env, func),
            &None => (String::new(), ";".into())
        }
    }
}

fn from_glib_xxx(transfer: library::Transfer) -> (String, String) {
    use library::Transfer::*;
    match transfer {
        None => ("from_glib_none(".into(), ")".into()),
        Full => ("from_glib_full(".into(), ")".into()),
        Container => ("TODO:".into(), String::new()),
    }
}
<commit_msg>Make Option<String> return value conversion<commit_after>use analysis;
use analysis::rust_type::rust_type;
use analysis::type_kind::TypeKind;
use env::Env;
use library;
use traits::*;

pub trait TranslateFromGlib {
    fn translate_from_glib_as_function(&self, env: &Env,
        func: &analysis::functions::Info) -> (String, String);
}

impl TranslateFromGlib for library::Parameter {
    fn translate_from_glib_as_function(&self,
        env: &Env, func: &analysis::functions::Info) -> (String, String) {
        let kind = TypeKind::of(&env.library, self.typ);
        if func.kind == library::FunctionKind::Constructor {
            let rust_type = rust_type(env, self.typ);
            if rust_type.as_str() != func.class_name.as_str() {
                let from_glib_xxx = from_glib_xxx(self.transfer);
                (
                    format!("{}::{}", rust_type.as_str(), from_glib_xxx.0),
                    format!("{}.downcast_unchecked()",from_glib_xxx.1)
                )
            } else {
                ("TODO:constructors_body ".into(), String::new())
            }
        } else {
            match kind {
                TypeKind::Converted => ("from_glib(".into(), ")".into()),
                TypeKind::Direct |
                    TypeKind::Enumeration => (String::new(), String::new()),
                //TODO: check gtk_dialog_get_content_area <type name="Box" c:type="GtkWidget*"/>
                TypeKind::Pointer | //Checked only for Option<String>
                    TypeKind::Object => from_glib_xxx(self.transfer),
                _ => (format!("TODO {:?}:", kind), String::new()),
            }
        }
    }
}

impl TranslateFromGlib for Option<library::Parameter> {
    fn translate_from_glib_as_function(&self, env: &Env,
        func: &analysis::functions::Info) -> (String, String) {
        match self {
            &Some(ref par) => par.translate_from_glib_as_function(env, func),
            &None => (String::new(), ";".into())
        }
    }
}

fn from_glib_xxx(transfer: library::Transfer) -> (String, String) {
    use library::Transfer::*;
    match transfer {
        None => ("from_glib_none(".into(), ")".into()),
        Full => ("from_glib_full(".into(), ")".into()),
        Container => ("TODO:".into(), String::new()),
    }
}
<|endoftext|>


<commit_before><commit_msg>Slight refactoring of the mutex module<commit_after><|endoftext|>


<commit_before>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::libc::c_ulonglong;
use core::option::{Option, Some, None};
use core::vec;
use lib::llvm::{ValueRef, TypeRef, True, False};
use middle::trans::_match;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::machine;
use middle::trans::type_of;
use middle::ty;
use syntax::ast;
use util::ppaux::ty_to_str;

// XXX: should this be done with boxed traits instead of ML-style?
pub enum Repr {
    CEnum(int, int), /* discriminant range */
    Univariant(Struct, Destructor),
    General(~[Struct])
}

enum Destructor {
    DtorPresent,
    DtorAbsent,
    NoDtor
}

struct Struct {
    size: u64,
    align: u64,
    fields: ~[ty::t]
}

pub fn represent_node(bcx: block, node: ast::node_id)
    -> Repr {
    represent_type(bcx.ccx(), node_id_type(bcx, node))
}

pub fn represent_type(cx: @CrateContext, t: ty::t) -> Repr {
    debug!("Representing: %s", ty_to_str(cx.tcx, t));
    // XXX: cache this
    match ty::get(t).sty {
        ty::ty_tup(ref elems) => {
            Univariant(mk_struct(cx, *elems), NoDtor)
        }
        ty::ty_rec(ref fields) => {
            // XXX: Are these in the right order?
            Univariant(mk_struct(cx, fields.map(|f| f.mt.ty)), DtorAbsent)
        }
        ty::ty_struct(def_id, ref substs) => {
            let fields = ty::lookup_struct_fields(cx.tcx, def_id);
            let dt = ty::ty_dtor(cx.tcx, def_id).is_present();
            Univariant(mk_struct(cx, fields.map(|field| {
                ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
            })), if dt { DtorPresent } else { DtorAbsent })
        }
        ty::ty_enum(def_id, ref substs) => {
            struct Case { discr: int, tys: ~[ty::t] };

            let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| {
                let arg_tys = do vi.args.map |&raw_ty| {
                    ty::subst(cx.tcx, substs, raw_ty)
                };
                Case { discr: vi.disr_val, tys: arg_tys }
            };
            if cases.len() == 0 {
                // Uninhabitable; represent as unit
                Univariant(mk_struct(cx, ~[]), NoDtor)
            } else if cases.len() == 1 && cases[0].discr == 0 {
                // struct, tuple, newtype, etc.
                Univariant(mk_struct(cx, cases[0].tys), NoDtor)
            } else if cases.all(|c| c.tys.len() == 0) {
                let discrs = cases.map(|c| c.discr);
                CEnum(discrs.min(), discrs.max())
            } else {
                if !cases.alli(|i,c| c.discr == (i as int)) {
                    cx.sess.bug(fmt!("non-C-like enum %s with specified \
                                      discriminants",
                                     ty::item_path_str(cx.tcx, def_id)))
                }
                General(cases.map(|c| mk_struct(cx, c.tys)))
            }
        }
        _ => cx.sess.bug(~"adt::represent_type called on non-ADT type")
    }
}

fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct {
    let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
    let llty_rec = T_struct(lltys);
    Struct {
        size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
        align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
        fields: vec::from_slice(tys)
    }
}

pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, true)
}
pub fn fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, false)
}
fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
    -> ~[TypeRef] {
    match *r {
        CEnum(*) => ~[T_enum_discrim(cx)],
        Univariant(ref st, dt) => {
            let f = if sizing {
                st.fields.map(|&ty| type_of::sizing_type_of(cx, ty))
            } else {
                st.fields.map(|&ty| type_of::type_of(cx, ty))
            };
            match dt {
                NoDtor => f,
                DtorAbsent => ~[T_struct(f)],
                DtorPresent => ~[T_struct(f), T_i8()]
            }
        }
        General(ref sts) => {
            ~[T_enum_discrim(cx),
              T_array(T_i8(), sts.map(|st| st.size).max() /*bad*/as uint)]
        }
    }
}

fn load_discr(bcx: block, scrutinee: ValueRef, min: int, max: int)
    -> ValueRef {
    let ptr = GEPi(bcx, scrutinee, [0, 0]);
    if max + 1 == min {
        // i.e., if the range is everything.  The lo==hi case would be
        // rejected by the LLVM verifier (it would mean either an
        // empty set, which is impossible, or the entire range of the
        // type, which is pointless).
        Load(bcx, ptr)
    } else {
        // llvm::ConstantRange can deal with ranges that wrap around,
        // so an overflow on (max + 1) is fine.
        LoadRangeAssert(bcx, ptr, min as c_ulonglong,
                        (max + 1) as c_ulonglong,
                        /* signed: */ True)
    }
}

pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef) ->
    (_match::branch_kind, Option<ValueRef>) {
    match *r {
        CEnum(min, max) => {
            (_match::switch, Some(load_discr(bcx, scrutinee, min, max)))
        }
        Univariant(*) => {
            (_match::single, None)
        }
        General(ref cases) => {
            (_match::switch, Some(load_discr(bcx, scrutinee, 0,
                                             (cases.len() - 1) as int)))
        }
    }
}

pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
    match *r {
        CEnum(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
        Univariant(*) => {
            bcx.ccx().sess.bug(~"no cases for univariants or structs")
        }
        General(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
    }
}

pub fn trans_set_discr(bcx: block, r: &Repr, val: ValueRef, discr: int) {
    match *r {
        CEnum(min, max) => {
            assert min <= discr && discr <= max;
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
        Univariant(_, DtorPresent) => {
            assert discr == 0;
            Store(bcx, C_u8(1), GEPi(bcx, val, [0, 1]))
        }
        Univariant(*) => {
            assert discr == 0;
        }
        General(*) => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
    }
}

pub fn num_args(r: &Repr, discr: int) -> uint {
    match *r {
        CEnum(*) => 0,
        Univariant(ref st, _dt) => { assert discr == 0; st.fields.len() }
        General(ref cases) => cases[discr as uint].fields.len()
    }
}

pub fn trans_GEP(bcx: block, r: &Repr, val: ValueRef, discr: int, ix: uint)
    -> ValueRef {
    // Note: if this ever needs to generate conditionals (e.g., if we
    // decide to do some kind of cdr-coding-like non-unique repr
    // someday), it'll need to return a possibly-new bcx as well.
    match *r {
        CEnum(*) => {
            bcx.ccx().sess.bug(~"element access in C-like enum")
        }
        Univariant(ref st, dt) => {
            assert discr == 0;
            let val = match dt {
                NoDtor => val,
                DtorPresent | DtorAbsent => GEPi(bcx, val, [0, 0])
            };
            struct_GEP(bcx, st, val, ix, false)
        }
        General(ref cases) => {
            struct_GEP(bcx, &cases[discr as uint],
                       GEPi(bcx, val, [0, 1]), ix, true)
        }
    }
}

fn struct_GEP(bcx: block, st: &Struct, val: ValueRef, ix: uint,
              needs_cast: bool) -> ValueRef {
    let ccx = bcx.ccx();

    let val = if needs_cast {
        let real_llty = T_struct(st.fields.map(
            |&ty| type_of::type_of(ccx, ty)));
        PointerCast(bcx, val, T_ptr(real_llty))
    } else {
        val
    };

    GEPi(bcx, val, [0, ix])
}

pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
                   vals: &[ValueRef]) -> ValueRef {
    match *r {
        CEnum(min, max) => {
            assert vals.len() == 0;
            assert min <= discr && discr <= max;
            C_int(ccx, discr)
        }
        Univariant(ref st, _dt) => {
            assert discr == 0;
            // consts are never destroyed, so the dtor flag is not needed
            C_struct(build_const_struct(ccx, st, vals))
        }
        General(ref cases) => {
            let case = &cases[discr as uint];
            let max_sz = cases.map(|s| s.size).max();
            let body = build_const_struct(ccx, case, vals);

            C_struct([C_int(ccx, discr),
                      C_packed_struct([C_struct(body)]),
                      padding(max_sz - case.size)])
        }
    }
}

fn padding(size: u64) -> ValueRef {
    C_undef(T_array(T_i8(), size /*bad*/as uint))
}

fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef])
    -> ~[ValueRef] {
    assert vals.len() == st.fields.len();

    let mut offset = 0;
    let mut cfields = ~[];
    for st.fields.eachi |i, &ty| {
        let llty = type_of::sizing_type_of(ccx, ty);
        let type_align = machine::llalign_of_min(ccx, llty)
            /*bad*/as u64;
        let val_align = machine::llalign_of_min(ccx, val_ty(vals[i]))
            /*bad*/as u64;
        let target_offset = roundup(offset, type_align);
        offset = roundup(offset, val_align);
        if (offset != target_offset) {
            cfields.push(padding(target_offset - offset));
            offset = target_offset;
        }
        assert !is_undef(vals[i]);
        // If that assert fails, could change it to wrap in a struct?
        cfields.push(vals[i]);
    }

    return cfields;
}

#[always_inline]
fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }

pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef)
    -> int {
    match *r {
        CEnum(*) => const_to_int(val) as int,
        Univariant(*) => 0,
        General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int,
    }
}

pub fn const_get_element(ccx: @CrateContext, r: &Repr, val: ValueRef,
                         _discr: int, ix: uint) -> ValueRef {
    // Not to be confused with common::const_get_elt.
    match *r {
        CEnum(*) => ccx.sess.bug(~"element access in C-like enum const"),
        Univariant(*) => const_struct_field(ccx, val, ix),
        General(*) => const_struct_field(ccx, const_get_elt(ccx, val,
                                                            [1, 0]), ix)
    }
}

fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
    -> ValueRef {
    // Get the ix-th non-undef element of the struct.
    let mut real_ix = 0; // actual position in the struct
    let mut ix = ix; // logical index relative to real_ix
    let mut field;
    loop {
        loop {
            field = const_get_elt(ccx, val, [real_ix]);
            if !is_undef(field) {
                break;
            }
            real_ix = real_ix + 1;
        }
        if ix == 0 {
            return field;
        }
        ix = ix - 1;
        real_ix = real_ix + 1;
    }
}
<commit_msg>Handle unit-like types specially.<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::libc::c_ulonglong;
use core::option::{Option, Some, None};
use core::vec;
use lib::llvm::{ValueRef, TypeRef, True, False};
use middle::trans::_match;
use middle::trans::build::*;
use middle::trans::common::*;
use middle::trans::machine;
use middle::trans::type_of;
use middle::ty;
use syntax::ast;
use util::ppaux::ty_to_str;

// XXX: should this be done with boxed traits instead of ML-style?
pub enum Repr {
    Unit(int),
    CEnum(int, int), /* discriminant range */
    Univariant(Struct, Destructor),
    General(~[Struct])
}

enum Destructor {
    DtorPresent,
    DtorAbsent,
    NoDtor
}

struct Struct {
    size: u64,
    align: u64,
    fields: ~[ty::t]
}

pub fn represent_node(bcx: block, node: ast::node_id)
    -> Repr {
    represent_type(bcx.ccx(), node_id_type(bcx, node))
}

pub fn represent_type(cx: @CrateContext, t: ty::t) -> Repr {
    debug!("Representing: %s", ty_to_str(cx.tcx, t));
    // XXX: cache this
    match ty::get(t).sty {
        ty::ty_tup(ref elems) => {
            Univariant(mk_struct(cx, *elems), NoDtor)
        }
        ty::ty_rec(ref fields) => {
            // XXX: Are these in the right order?
            Univariant(mk_struct(cx, fields.map(|f| f.mt.ty)), DtorAbsent)
        }
        ty::ty_struct(def_id, ref substs) => {
            let fields = ty::lookup_struct_fields(cx.tcx, def_id);
            let dt = ty::ty_dtor(cx.tcx, def_id).is_present();
            Univariant(mk_struct(cx, fields.map(|field| {
                ty::lookup_field_type(cx.tcx, def_id, field.id, substs)
            })), if dt { DtorPresent } else { DtorAbsent })
        }
        ty::ty_enum(def_id, ref substs) => {
            struct Case { discr: int, tys: ~[ty::t] };

            let cases = do ty::enum_variants(cx.tcx, def_id).map |vi| {
                let arg_tys = do vi.args.map |&raw_ty| {
                    ty::subst(cx.tcx, substs, raw_ty)
                };
                Case { discr: vi.disr_val, tys: arg_tys }
            };
            if cases.len() == 0 {
                // Uninhabitable; represent as unit
                Univariant(mk_struct(cx, ~[]), NoDtor)
            } else if cases.len() == 1 && cases[0].tys.len() == 0 {
                Unit(cases[0].discr)
            } else if cases.len() == 1 {
                // struct, tuple, newtype, etc.
                assert cases[0].discr == 0;
                Univariant(mk_struct(cx, cases[0].tys), NoDtor)
            } else if cases.all(|c| c.tys.len() == 0) {
                let discrs = cases.map(|c| c.discr);
                CEnum(discrs.min(), discrs.max())
            } else {
                if !cases.alli(|i,c| c.discr == (i as int)) {
                    cx.sess.bug(fmt!("non-C-like enum %s with specified \
                                      discriminants",
                                     ty::item_path_str(cx.tcx, def_id)))
                }
                General(cases.map(|c| mk_struct(cx, c.tys)))
            }
        }
        _ => cx.sess.bug(~"adt::represent_type called on non-ADT type")
    }
}

fn mk_struct(cx: @CrateContext, tys: &[ty::t]) -> Struct {
    let lltys = tys.map(|&ty| type_of::sizing_type_of(cx, ty));
    let llty_rec = T_struct(lltys);
    Struct {
        size: machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64,
        align: machine::llalign_of_min(cx, llty_rec) /*bad*/as u64,
        fields: vec::from_slice(tys)
    }
}

pub fn sizing_fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, true)
}
pub fn fields_of(cx: @CrateContext, r: &Repr) -> ~[TypeRef] {
    generic_fields_of(cx, r, false)
}
fn generic_fields_of(cx: @CrateContext, r: &Repr, sizing: bool)
    -> ~[TypeRef] {
    match *r {
        Unit(*) => ~[],
        CEnum(*) => ~[T_enum_discrim(cx)],
        Univariant(ref st, dt) => {
            let f = if sizing {
                st.fields.map(|&ty| type_of::sizing_type_of(cx, ty))
            } else {
                st.fields.map(|&ty| type_of::type_of(cx, ty))
            };
            match dt {
                NoDtor => f,
                DtorAbsent => ~[T_struct(f)],
                DtorPresent => ~[T_struct(f), T_i8()]
            }
        }
        General(ref sts) => {
            ~[T_enum_discrim(cx),
              T_array(T_i8(), sts.map(|st| st.size).max() /*bad*/as uint)]
        }
    }
}

fn load_discr(bcx: block, scrutinee: ValueRef, min: int, max: int)
    -> ValueRef {
    let ptr = GEPi(bcx, scrutinee, [0, 0]);
    if max + 1 == min {
        // i.e., if the range is everything.  The lo==hi case would be
        // rejected by the LLVM verifier (it would mean either an
        // empty set, which is impossible, or the entire range of the
        // type, which is pointless).
        Load(bcx, ptr)
    } else {
        // llvm::ConstantRange can deal with ranges that wrap around,
        // so an overflow on (max + 1) is fine.
        LoadRangeAssert(bcx, ptr, min as c_ulonglong,
                        (max + 1) as c_ulonglong,
                        /* signed: */ True)
    }
}

pub fn trans_switch(bcx: block, r: &Repr, scrutinee: ValueRef) ->
    (_match::branch_kind, Option<ValueRef>) {
    match *r {
        CEnum(min, max) => {
            (_match::switch, Some(load_discr(bcx, scrutinee, min, max)))
        }
        Unit(*) | Univariant(*) => {
            (_match::single, None)
        }
        General(ref cases) => {
            (_match::switch, Some(load_discr(bcx, scrutinee, 0,
                                             (cases.len() - 1) as int)))
        }
    }
}

pub fn trans_case(bcx: block, r: &Repr, discr: int) -> _match::opt_result {
    match *r {
        CEnum(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
        Unit(*) | Univariant(*)=> {
            bcx.ccx().sess.bug(~"no cases for univariants or structs")
        }
        General(*) => {
            _match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
        }
    }
}

pub fn trans_set_discr(bcx: block, r: &Repr, val: ValueRef, discr: int) {
    match *r {
        Unit(the_discr) => {
            assert discr == the_discr;
        }
        CEnum(min, max) => {
            assert min <= discr && discr <= max;
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
        Univariant(_, DtorPresent) => {
            assert discr == 0;
            Store(bcx, C_u8(1), GEPi(bcx, val, [0, 1]))
        }
        Univariant(*) => {
            assert discr == 0;
        }
        General(*) => {
            Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
        }
    }
}

pub fn num_args(r: &Repr, discr: int) -> uint {
    match *r {
        Unit(*) | CEnum(*) => 0,
        Univariant(ref st, _dt) => { assert discr == 0; st.fields.len() }
        General(ref cases) => cases[discr as uint].fields.len()
    }
}

pub fn trans_GEP(bcx: block, r: &Repr, val: ValueRef, discr: int, ix: uint)
    -> ValueRef {
    // Note: if this ever needs to generate conditionals (e.g., if we
    // decide to do some kind of cdr-coding-like non-unique repr
    // someday), it'll need to return a possibly-new bcx as well.
    match *r {
        Unit(*) | CEnum(*) => {
            bcx.ccx().sess.bug(~"element access in C-like enum")
        }
        Univariant(ref st, dt) => {
            assert discr == 0;
            let val = match dt {
                NoDtor => val,
                DtorPresent | DtorAbsent => GEPi(bcx, val, [0, 0])
            };
            struct_GEP(bcx, st, val, ix, false)
        }
        General(ref cases) => {
            struct_GEP(bcx, &cases[discr as uint],
                       GEPi(bcx, val, [0, 1]), ix, true)
        }
    }
}

fn struct_GEP(bcx: block, st: &Struct, val: ValueRef, ix: uint,
              needs_cast: bool) -> ValueRef {
    let ccx = bcx.ccx();

    let val = if needs_cast {
        let real_llty = T_struct(st.fields.map(
            |&ty| type_of::type_of(ccx, ty)));
        PointerCast(bcx, val, T_ptr(real_llty))
    } else {
        val
    };

    GEPi(bcx, val, [0, ix])
}

pub fn trans_const(ccx: @CrateContext, r: &Repr, discr: int,
                   vals: &[ValueRef]) -> ValueRef {
    match *r {
        Unit(*) => {
            C_struct(~[])
        }
        CEnum(min, max) => {
            assert vals.len() == 0;
            assert min <= discr && discr <= max;
            C_int(ccx, discr)
        }
        Univariant(ref st, _dt) => {
            assert discr == 0;
            // consts are never destroyed, so the dtor flag is not needed
            C_struct(build_const_struct(ccx, st, vals))
        }
        General(ref cases) => {
            let case = &cases[discr as uint];
            let max_sz = cases.map(|s| s.size).max();
            let body = build_const_struct(ccx, case, vals);

            C_struct([C_int(ccx, discr),
                      C_packed_struct([C_struct(body)]),
                      padding(max_sz - case.size)])
        }
    }
}

fn padding(size: u64) -> ValueRef {
    C_undef(T_array(T_i8(), size /*bad*/as uint))
}

fn build_const_struct(ccx: @CrateContext, st: &Struct, vals: &[ValueRef])
    -> ~[ValueRef] {
    assert vals.len() == st.fields.len();

    let mut offset = 0;
    let mut cfields = ~[];
    for st.fields.eachi |i, &ty| {
        let llty = type_of::sizing_type_of(ccx, ty);
        let type_align = machine::llalign_of_min(ccx, llty)
            /*bad*/as u64;
        let val_align = machine::llalign_of_min(ccx, val_ty(vals[i]))
            /*bad*/as u64;
        let target_offset = roundup(offset, type_align);
        offset = roundup(offset, val_align);
        if (offset != target_offset) {
            cfields.push(padding(target_offset - offset));
            offset = target_offset;
        }
        assert !is_undef(vals[i]);
        // If that assert fails, could change it to wrap in a struct?
        cfields.push(vals[i]);
    }

    return cfields;
}

#[always_inline]
fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }

pub fn const_get_discrim(ccx: @CrateContext, r: &Repr, val: ValueRef)
    -> int {
    match *r {
        Unit(discr) => discr,
        CEnum(*) => const_to_int(val) as int,
        Univariant(*) => 0,
        General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int,
    }
}

pub fn const_get_element(ccx: @CrateContext, r: &Repr, val: ValueRef,
                         _discr: int, ix: uint) -> ValueRef {
    // Not to be confused with common::const_get_elt.
    match *r {
        Unit(*) | CEnum(*) => ccx.sess.bug(~"element access in C-like enum \
                                             const"),
        Univariant(*) => const_struct_field(ccx, val, ix),
        General(*) => const_struct_field(ccx, const_get_elt(ccx, val,
                                                            [1, 0]), ix)
    }
}

fn const_struct_field(ccx: @CrateContext, val: ValueRef, ix: uint)
    -> ValueRef {
    // Get the ix-th non-undef element of the struct.
    let mut real_ix = 0; // actual position in the struct
    let mut ix = ix; // logical index relative to real_ix
    let mut field;
    loop {
        loop {
            field = const_get_elt(ccx, val, [real_ix]);
            if !is_undef(field) {
                break;
            }
            real_ix = real_ix + 1;
        }
        if ix == 0 {
            return field;
        }
        ix = ix - 1;
        real_ix = real_ix + 1;
    }
}
<|endoftext|>


<commit_before>//! Connection pooling via r2d2.
//!
//! Note: This module requires enabling the `r2d2` feature

pub use r2d2::*;

/// A re-export of [`r2d2::Error`], which is only used by methods on [`r2d2::Pool`].
///
/// [`r2d2::Error`]: r2d2::Error
/// [`r2d2::Pool`]: r2d2::Pool
pub type PoolError = r2d2::Error;

use std::convert::Into;
use std::fmt;
use std::marker::PhantomData;

use crate::backend::Backend;
use crate::connection::commit_error_processor::{CommitErrorOutcome, CommitErrorProcessor};
use crate::connection::{
    ConnectionGatWorkaround, SimpleConnection, TransactionManager, TransactionManagerStatus,
};
use crate::expression::QueryMetadata;
use crate::prelude::*;
use crate::query_builder::{Query, QueryFragment, QueryId};

/// An r2d2 connection manager for use with Diesel.
///
/// See the [r2d2 documentation] for usage examples.
///
/// [r2d2 documentation]: r2d2
#[derive(Clone)]
pub struct ConnectionManager<T> {
    database_url: String,
    _marker: PhantomData<T>,
}

impl<T> fmt::Debug for ConnectionManager<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "ConnectionManager<{}>", std::any::type_name::<T>())
    }
}

unsafe impl<T: Send + 'static> Sync for ConnectionManager<T> {}

impl<T> ConnectionManager<T> {
    /// Returns a new connection manager,
    /// which establishes connections to the given database URL.
    pub fn new<S: Into<String>>(database_url: S) -> Self {
        ConnectionManager {
            database_url: database_url.into(),
            _marker: PhantomData,
        }
    }
}

/// The error used when managing connections with `r2d2`.
#[derive(Debug)]
pub enum Error {
    /// An error occurred establishing the connection
    ConnectionError(ConnectionError),

    /// An error occurred pinging the database
    QueryError(crate::result::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Error::ConnectionError(ref e) => e.fmt(f),
            Error::QueryError(ref e) => e.fmt(f),
        }
    }
}

impl ::std::error::Error for Error {}

/// A trait indicating a connection could be used inside a r2d2 pool
pub trait R2D2Connection: Connection {
    /// Check if a connection is still valid
    fn ping(&mut self) -> QueryResult<()>;

    /// Checks if the connection is broken and should not be reused
    ///
    /// This method should return only contain a fast non-blocking check
    /// if the connection is considered to be broken or not. See
    /// [ManageConnection::has_broken] for details.
    ///
    /// The default implementation does not consider any connection as broken
    fn is_broken(&mut self) -> bool {
        false
    }
}

impl<T> ManageConnection for ConnectionManager<T>
where
    T: R2D2Connection + Send + 'static,
{
    type Connection = T;
    type Error = Error;

    fn connect(&self) -> Result<T, Error> {
        T::establish(&self.database_url).map_err(Error::ConnectionError)
    }

    fn is_valid(&self, conn: &mut T) -> Result<(), Error> {
        conn.ping().map_err(Error::QueryError)
    }

    fn has_broken(&self, conn: &mut T) -> bool {
        std::thread::panicking() || conn.is_broken()
    }
}

impl<M> SimpleConnection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: R2D2Connection + Send + 'static,
{
    fn batch_execute(&mut self, query: &str) -> QueryResult<()> {
        (&mut **self).batch_execute(query)
    }
}

impl<'conn, 'query, DB, M> ConnectionGatWorkaround<'conn, 'query, DB> for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: Connection<Backend = DB>,
    DB: Backend,
{
    type Cursor = <M::Connection as ConnectionGatWorkaround<'conn, 'query, DB>>::Cursor;
    type Row = <M::Connection as ConnectionGatWorkaround<'conn, 'query, DB>>::Row;
}

impl<M> CommitErrorProcessor for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: R2D2Connection + CommitErrorProcessor + Send + 'static,
{
    fn process_commit_error(&self, error: crate::result::Error) -> CommitErrorOutcome {
        (&**self).process_commit_error(error)
    }
}

impl<M> Connection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: Connection + R2D2Connection + Send + 'static,
{
    type Backend = <M::Connection as Connection>::Backend;
    type TransactionManager =
        PoolTransactionManager<<M::Connection as Connection>::TransactionManager>;

    fn establish(_: &str) -> ConnectionResult<Self> {
        Err(ConnectionError::BadConnection(String::from(
            "Cannot directly establish a pooled connection",
        )))
    }

    fn load<'conn, 'query, T>(
        &'conn mut self,
        source: T,
    ) -> QueryResult<<Self as ConnectionGatWorkaround<'conn, 'query, Self::Backend>>::Cursor>
    where
        T: Query + QueryFragment<Self::Backend> + QueryId + 'query,
        Self::Backend: QueryMetadata<T::SqlType>,
    {
        (&mut **self).load(source)
    }

    fn execute_returning_count<T>(&mut self, source: &T) -> QueryResult<usize>
    where
        T: QueryFragment<Self::Backend> + QueryId,
    {
        (&mut **self).execute_returning_count(source)
    }

    fn transaction_state(
        &mut self,
    ) -> &mut <Self::TransactionManager as TransactionManager<Self>>::TransactionStateData {
        (&mut **self).transaction_state()
    }

    fn begin_test_transaction(&mut self) -> QueryResult<()> {
        (&mut **self).begin_test_transaction()
    }
}

#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct PoolTransactionManager<T>(std::marker::PhantomData<T>);

impl<M, T> TransactionManager<PooledConnection<M>> for PoolTransactionManager<T>
where
    M: ManageConnection,
    M::Connection: Connection<TransactionManager = T> + R2D2Connection,
    T: TransactionManager<M::Connection>,
{
    type TransactionStateData = T::TransactionStateData;

    fn begin_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
        T::begin_transaction(&mut **conn)
    }

    fn rollback_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
        T::rollback_transaction(&mut **conn)
    }

    fn commit_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
        T::commit_transaction(&mut **conn)
    }

    fn transaction_manager_status_mut(
        conn: &mut PooledConnection<M>,
    ) -> &mut TransactionManagerStatus {
        T::transaction_manager_status_mut(&mut **conn)
    }
}

impl<M> crate::migration::MigrationConnection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: crate::migration::MigrationConnection,
    Self: Connection,
{
    fn setup(&mut self) -> QueryResult<usize> {
        (&mut **self).setup()
    }
}

impl<Changes, Output, M> crate::query_dsl::UpdateAndFetchResults<Changes, Output>
    for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: crate::query_dsl::UpdateAndFetchResults<Changes, Output>,
    Self: Connection,
{
    fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output> {
        (&mut **self).update_and_fetch(changeset)
    }
}

#[cfg(test)]
mod tests {
    use std::sync::mpsc;
    use std::sync::Arc;
    use std::thread;

    use crate::r2d2::*;
    use crate::test_helpers::*;

    #[test]
    fn establish_basic_connection() {
        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Arc::new(Pool::builder().max_size(2).build(manager).unwrap());

        let (s1, r1) = mpsc::channel();
        let (s2, r2) = mpsc::channel();

        let pool1 = Arc::clone(&pool);
        let t1 = thread::spawn(move || {
            let conn = pool1.get().unwrap();
            s1.send(()).unwrap();
            r2.recv().unwrap();
            drop(conn);
        });

        let pool2 = Arc::clone(&pool);
        let t2 = thread::spawn(move || {
            let conn = pool2.get().unwrap();
            s2.send(()).unwrap();
            r1.recv().unwrap();
            drop(conn);
        });

        t1.join().unwrap();
        t2.join().unwrap();

        pool.get().unwrap();
    }

    #[test]
    fn is_valid() {
        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Pool::builder()
            .max_size(1)
            .test_on_check_out(true)
            .build(manager)
            .unwrap();

        pool.get().unwrap();
    }

    #[test]
    fn pooled_connection_impls_connection() {
        use crate::select;
        use crate::sql_types::Text;

        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Pool::builder()
            .max_size(1)
            .test_on_check_out(true)
            .build(manager)
            .unwrap();
        let mut conn = pool.get().unwrap();

        let query = select("foo".into_sql::<Text>());
        assert_eq!("foo", query.get_result::<String>(&mut conn).unwrap());
    }
}

#[derive(QueryId)]
pub(crate) struct CheckConnectionQuery;

impl<DB> QueryFragment<DB> for CheckConnectionQuery
where
    DB: Backend,
{
    fn walk_ast<'b>(
        &'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
    ) -> QueryResult<()> {
        pass.push_sql("SELECT 1");
        Ok(())
    }
}

impl Query for CheckConnectionQuery {
    type SqlType = crate::sql_types::Integer;
}

impl<C> RunQueryDsl<C> for CheckConnectionQuery {}
<commit_msg>Add documentation to diesel's r2d2 module on what happens when connections fail inside a pool<commit_after>//! Connection pooling via r2d2.
//!
//! Note: This module requires enabling the `r2d2` feature
//!
//! When used inside a pool, if an individual connection becomes
//! broken (as determined by the [R2D2Connection::is_broken] method)
//! then `r2d2` will put close and return the connection to the DB.
//!
//! `diesel` determines broken connections by whether or not the current
//! thread is panicking or if individual `Connection` structs are
//! broken (determined by the `is_broken()` method). Generically, these
//! are left to individual backends to implement themselves.
//!
//! For SQLite, PG, and MySQL backends, specifically, `is_broken()`
//! is determined by whether or not the `TransactionManagerStatus` (as a part
//! of the `AnsiTransactionManager` struct) is in an `InError` state.
//!

pub use r2d2::*;

/// A re-export of [`r2d2::Error`], which is only used by methods on [`r2d2::Pool`].
///
/// [`r2d2::Error`]: r2d2::Error
/// [`r2d2::Pool`]: r2d2::Pool
pub type PoolError = r2d2::Error;

use std::convert::Into;
use std::fmt;
use std::marker::PhantomData;

use crate::backend::Backend;
use crate::connection::commit_error_processor::{CommitErrorOutcome, CommitErrorProcessor};
use crate::connection::{
    ConnectionGatWorkaround, SimpleConnection, TransactionManager, TransactionManagerStatus,
};
use crate::expression::QueryMetadata;
use crate::prelude::*;
use crate::query_builder::{Query, QueryFragment, QueryId};

/// An r2d2 connection manager for use with Diesel.
///
/// See the [r2d2 documentation] for usage examples.
///
/// [r2d2 documentation]: r2d2
#[derive(Clone)]
pub struct ConnectionManager<T> {
    database_url: String,
    _marker: PhantomData<T>,
}

impl<T> fmt::Debug for ConnectionManager<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "ConnectionManager<{}>", std::any::type_name::<T>())
    }
}

unsafe impl<T: Send + 'static> Sync for ConnectionManager<T> {}

impl<T> ConnectionManager<T> {
    /// Returns a new connection manager,
    /// which establishes connections to the given database URL.
    pub fn new<S: Into<String>>(database_url: S) -> Self {
        ConnectionManager {
            database_url: database_url.into(),
            _marker: PhantomData,
        }
    }
}

/// The error used when managing connections with `r2d2`.
#[derive(Debug)]
pub enum Error {
    /// An error occurred establishing the connection
    ConnectionError(ConnectionError),

    /// An error occurred pinging the database
    QueryError(crate::result::Error),
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match *self {
            Error::ConnectionError(ref e) => e.fmt(f),
            Error::QueryError(ref e) => e.fmt(f),
        }
    }
}

impl ::std::error::Error for Error {}

/// A trait indicating a connection could be used inside a r2d2 pool
pub trait R2D2Connection: Connection {
    /// Check if a connection is still valid
    fn ping(&mut self) -> QueryResult<()>;

    /// Checks if the connection is broken and should not be reused
    ///
    /// This method should return only contain a fast non-blocking check
    /// if the connection is considered to be broken or not. See
    /// [ManageConnection::has_broken] for details.
    ///
    /// The default implementation does not consider any connection as broken
    fn is_broken(&mut self) -> bool {
        false
    }
}

impl<T> ManageConnection for ConnectionManager<T>
where
    T: R2D2Connection + Send + 'static,
{
    type Connection = T;
    type Error = Error;

    fn connect(&self) -> Result<T, Error> {
        T::establish(&self.database_url).map_err(Error::ConnectionError)
    }

    fn is_valid(&self, conn: &mut T) -> Result<(), Error> {
        conn.ping().map_err(Error::QueryError)
    }

    fn has_broken(&self, conn: &mut T) -> bool {
        std::thread::panicking() || conn.is_broken()
    }
}

impl<M> SimpleConnection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: R2D2Connection + Send + 'static,
{
    fn batch_execute(&mut self, query: &str) -> QueryResult<()> {
        (&mut **self).batch_execute(query)
    }
}

impl<'conn, 'query, DB, M> ConnectionGatWorkaround<'conn, 'query, DB> for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: Connection<Backend = DB>,
    DB: Backend,
{
    type Cursor = <M::Connection as ConnectionGatWorkaround<'conn, 'query, DB>>::Cursor;
    type Row = <M::Connection as ConnectionGatWorkaround<'conn, 'query, DB>>::Row;
}

impl<M> CommitErrorProcessor for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: R2D2Connection + CommitErrorProcessor + Send + 'static,
{
    fn process_commit_error(&self, error: crate::result::Error) -> CommitErrorOutcome {
        (&**self).process_commit_error(error)
    }
}

impl<M> Connection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: Connection + R2D2Connection + Send + 'static,
{
    type Backend = <M::Connection as Connection>::Backend;
    type TransactionManager =
        PoolTransactionManager<<M::Connection as Connection>::TransactionManager>;

    fn establish(_: &str) -> ConnectionResult<Self> {
        Err(ConnectionError::BadConnection(String::from(
            "Cannot directly establish a pooled connection",
        )))
    }

    fn load<'conn, 'query, T>(
        &'conn mut self,
        source: T,
    ) -> QueryResult<<Self as ConnectionGatWorkaround<'conn, 'query, Self::Backend>>::Cursor>
    where
        T: Query + QueryFragment<Self::Backend> + QueryId + 'query,
        Self::Backend: QueryMetadata<T::SqlType>,
    {
        (&mut **self).load(source)
    }

    fn execute_returning_count<T>(&mut self, source: &T) -> QueryResult<usize>
    where
        T: QueryFragment<Self::Backend> + QueryId,
    {
        (&mut **self).execute_returning_count(source)
    }

    fn transaction_state(
        &mut self,
    ) -> &mut <Self::TransactionManager as TransactionManager<Self>>::TransactionStateData {
        (&mut **self).transaction_state()
    }

    fn begin_test_transaction(&mut self) -> QueryResult<()> {
        (&mut **self).begin_test_transaction()
    }
}

#[doc(hidden)]
#[allow(missing_debug_implementations)]
pub struct PoolTransactionManager<T>(std::marker::PhantomData<T>);

impl<M, T> TransactionManager<PooledConnection<M>> for PoolTransactionManager<T>
where
    M: ManageConnection,
    M::Connection: Connection<TransactionManager = T> + R2D2Connection,
    T: TransactionManager<M::Connection>,
{
    type TransactionStateData = T::TransactionStateData;

    fn begin_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
        T::begin_transaction(&mut **conn)
    }

    fn rollback_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
        T::rollback_transaction(&mut **conn)
    }

    fn commit_transaction(conn: &mut PooledConnection<M>) -> QueryResult<()> {
        T::commit_transaction(&mut **conn)
    }

    fn transaction_manager_status_mut(
        conn: &mut PooledConnection<M>,
    ) -> &mut TransactionManagerStatus {
        T::transaction_manager_status_mut(&mut **conn)
    }
}

impl<M> crate::migration::MigrationConnection for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: crate::migration::MigrationConnection,
    Self: Connection,
{
    fn setup(&mut self) -> QueryResult<usize> {
        (&mut **self).setup()
    }
}

impl<Changes, Output, M> crate::query_dsl::UpdateAndFetchResults<Changes, Output>
    for PooledConnection<M>
where
    M: ManageConnection,
    M::Connection: crate::query_dsl::UpdateAndFetchResults<Changes, Output>,
    Self: Connection,
{
    fn update_and_fetch(&mut self, changeset: Changes) -> QueryResult<Output> {
        (&mut **self).update_and_fetch(changeset)
    }
}

#[cfg(test)]
mod tests {
    use std::sync::mpsc;
    use std::sync::Arc;
    use std::thread;

    use crate::r2d2::*;
    use crate::test_helpers::*;

    #[test]
    fn establish_basic_connection() {
        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Arc::new(Pool::builder().max_size(2).build(manager).unwrap());

        let (s1, r1) = mpsc::channel();
        let (s2, r2) = mpsc::channel();

        let pool1 = Arc::clone(&pool);
        let t1 = thread::spawn(move || {
            let conn = pool1.get().unwrap();
            s1.send(()).unwrap();
            r2.recv().unwrap();
            drop(conn);
        });

        let pool2 = Arc::clone(&pool);
        let t2 = thread::spawn(move || {
            let conn = pool2.get().unwrap();
            s2.send(()).unwrap();
            r1.recv().unwrap();
            drop(conn);
        });

        t1.join().unwrap();
        t2.join().unwrap();

        pool.get().unwrap();
    }

    #[test]
    fn is_valid() {
        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Pool::builder()
            .max_size(1)
            .test_on_check_out(true)
            .build(manager)
            .unwrap();

        pool.get().unwrap();
    }

    #[test]
    fn pooled_connection_impls_connection() {
        use crate::select;
        use crate::sql_types::Text;

        let manager = ConnectionManager::<TestConnection>::new(database_url());
        let pool = Pool::builder()
            .max_size(1)
            .test_on_check_out(true)
            .build(manager)
            .unwrap();
        let mut conn = pool.get().unwrap();

        let query = select("foo".into_sql::<Text>());
        assert_eq!("foo", query.get_result::<String>(&mut conn).unwrap());
    }
}

#[derive(QueryId)]
pub(crate) struct CheckConnectionQuery;

impl<DB> QueryFragment<DB> for CheckConnectionQuery
where
    DB: Backend,
{
    fn walk_ast<'b>(
        &'b self,
        mut pass: crate::query_builder::AstPass<'_, 'b, DB>,
    ) -> QueryResult<()> {
        pass.push_sql("SELECT 1");
        Ok(())
    }
}

impl Query for CheckConnectionQuery {
    type SqlType = crate::sql_types::Integer;
}

impl<C> RunQueryDsl<C> for CheckConnectionQuery {}
<|endoftext|>


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

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_DIRECTORY: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory() -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(XI_DIRECTORY);
            Ok(log_dir)
        }
        None => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "The dir library was not able to find a directory for this platform",
        )),
    }
}

fn path_for_log_file<P: AsRef<Path>>(filename: P) -> Result<PathBuf, io::Error> {
    let mut logging_directory = get_logging_directory()?;
    // Create the logging directory
    fs::create_dir_all(&logging_directory)?;
    logging_directory.push(filename.as_ref());
    Ok(logging_directory)
}

fn setup_logging() -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    match path_for_log_file(XI_LOG_FILE) {
        Ok(logging_file_path) => fern_dispatch
            .chain(fern::log_file(logging_file_path)?)
            .apply()?,
        Err(err) => {
            fern_dispatch.apply()?;
            warn!(
                "There was an issue getting the path for the log file: {}, falling back to stderr.",
                err,
            );
        }
    }
    info!("Logging with fern is setup");
    Ok(())
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    if let Err(e) = setup_logging() {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<commit_msg>Swapped to separate `if let`s to only call `.apply()?` once.<commit_after>// Copyright 2016 The xi-editor Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#[macro_use]
extern crate log;
extern crate chrono;
extern crate fern;

extern crate dirs;

extern crate xi_core_lib;
extern crate xi_rpc;

use std::fs;
use std::io;
use std::path::{Path, PathBuf};

use xi_core_lib::XiCore;
use xi_rpc::RpcLoop;

const XI_DIRECTORY: &str = "xi-core";
const XI_LOG_FILE: &str = "xi-core.log";

fn get_logging_directory() -> Result<PathBuf, io::Error> {
    match dirs::data_local_dir() {
        Some(mut log_dir) => {
            log_dir.push(XI_DIRECTORY);
            Ok(log_dir)
        }
        None => Err(io::Error::new(
            io::ErrorKind::NotFound,
            "The dir library was not able to find a directory for this platform",
        )),
    }
}

fn path_for_log_file<P: AsRef<Path>>(filename: P) -> Result<PathBuf, io::Error> {
    let mut logging_directory = get_logging_directory()?;
    // Create the logging directory
    fs::create_dir_all(&logging_directory)?;
    logging_directory.push(filename.as_ref());
    Ok(logging_directory)
}

fn setup_logging() -> Result<(), fern::InitError> {
    let level_filter = match std::env::var("XI_LOG") {
        Ok(level) => match level.to_lowercase().as_ref() {
            "trace" => log::LevelFilter::Trace,
            "debug" => log::LevelFilter::Debug,
            _ => log::LevelFilter::Info,
        },
        // Default to info
        Err(_) => log::LevelFilter::Info,
    };

    let mut fern_dispatch = fern::Dispatch::new()
        .format(|out, message, record| {
            out.finish(format_args!(
                "{}[{}][{}] {}",
                chrono::Local::now().format("[%Y-%m-%d][%H:%M:%S]"),
                record.target(),
                record.level(),
                message,
            ))
        }).level(level_filter)
        .chain(io::stderr());

    let path_result = path_for_log_file(XI_LOG_FILE);
    // If the logging_file_path returned successfully, add the logfile capability to fern
    if let Ok(logging_file_path) = &path_result {
        fern_dispatch = fern_dispatch.chain(fern::log_file(logging_file_path)?);
    }

    // Start fern
    fern_dispatch.apply()?;

    // If the logging_file_path returned an error, print it with fern/logs
    if let Err(e) = &path_result {
        let message = "There was an issue getting the path for the log file";
        warn!("{}: {:?}, falling back to stderr.", message, e);
    }

    info!("Logging with fern is setup");
    Ok(())
}

fn main() {
    let mut state = XiCore::new();
    let stdin = io::stdin();
    let stdout = io::stdout();
    let mut rpc_looper = RpcLoop::new(stdout);

    if let Err(e) = setup_logging() {
        eprintln!(
            "[ERROR] setup_logging returned error, logging disabled: {:?}",
            e
        );
    }

    match rpc_looper.mainloop(|| stdin.lock(), &mut state) {
        Ok(_) => (),
        Err(err) => error!("xi-core exited with error:\n{:?}", err),
    }
}
<|endoftext|>


<commit_before>#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter};
use std::io::*;
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        {
            let entries = [$(&stringify!([$arg]:), &$arg as &Debug),*];
            stderr().write_fmt(format_args!("{:#?}\n", entries)).unwrap();
        }
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

pub fn main() {
    println!("{}", 0)
}
<commit_msg>Improve debug! macro<commit_after>#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

// -----------------------------------------------
// Framework
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        $(writeln!(stderr(), "{} = {:?}", stringify!($arg), $arg).unwrap());*
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn main() {
    println!("{}", 0)
}
<|endoftext|>


<commit_before><commit_msg>Add headers test<commit_after><|endoftext|>