<commit_before>//! Defines the DifferentialGeometry type which is used to pass information
//! about the hit piece of geometry back from the intersection to the shading

use linalg::{self, Point, Normal, Vector};
use geometry::Geometry;

/// Stores information about a hit piece of geometry of some object in the scene
#[derive(Clone, Copy)]
pub struct DifferentialGeometry<'a> {
    /// The hit point
    pub p: Point,
    /// The shading normal
    pub n: Normal,
    /// The geometry normal
    pub ng: Normal,
    /// Derivative of the point with respect to the u parameterization coord of the surface
    pub dp_du: Vector,
    /// Derivative of the point with respect to the v parameterization coord of the surface
    pub dp_dv: Vector,
    /// The geometry that was hit
    pub geom: &'a (Geometry + 'a),
}

impl<'a> DifferentialGeometry<'a> {
    /// Setup the differential geometry. Note that the normal will be computed
    /// using cross(dp_du, dp_dv)
    pub fn new(p: &Point, ng: &Normal, dp_du: &Vector, dp_dv: &Vector,
               geom: &'a (Geometry + 'a))
               -> DifferentialGeometry<'a> {
        let n = linalg::cross(dp_du, dp_dv).normalized();
        DifferentialGeometry { p: *p, n: Normal::new(n.x, n.y, n.z), ng: *ng,
                               dp_du: *dp_du, dp_dv: *dp_dv, geom: geom }
    }
    /// Setup the differential geometry using the normal passed for the surface normal
    pub fn with_normal(p: &Point, n: &Normal, dp_du: &Vector, dp_dv: &Vector,
               geom: &'a (Geometry + 'a))
               -> DifferentialGeometry<'a> {
        DifferentialGeometry { p: *p, n: *n, ng: *n,
                               dp_du: *dp_du, dp_dv: *dp_dv, geom: geom }
    }
}

<commit_msg>Keep normal and geometry normal normalized<commit_after>//! Defines the DifferentialGeometry type which is used to pass information
//! about the hit piece of geometry back from the intersection to the shading

use linalg::{self, Point, Normal, Vector};
use geometry::Geometry;

/// Stores information about a hit piece of geometry of some object in the scene
#[derive(Clone, Copy)]
pub struct DifferentialGeometry<'a> {
    /// The hit point
    pub p: Point,
    /// The shading normal
    pub n: Normal,
    /// The geometry normal
    pub ng: Normal,
    /// Derivative of the point with respect to the u parameterization coord of the surface
    pub dp_du: Vector,
    /// Derivative of the point with respect to the v parameterization coord of the surface
    pub dp_dv: Vector,
    /// The geometry that was hit
    pub geom: &'a (Geometry + 'a),
}

impl<'a> DifferentialGeometry<'a> {
    /// Setup the differential geometry. Note that the normal will be computed
    /// using cross(dp_du, dp_dv)
    pub fn new(p: &Point, ng: &Normal, dp_du: &Vector, dp_dv: &Vector,
               geom: &'a (Geometry + 'a))
               -> DifferentialGeometry<'a> {
        let n = linalg::cross(dp_du, dp_dv).normalized();
        DifferentialGeometry { p: *p, n: Normal::new(n.x, n.y, n.z), ng: ng.normalized(),
                               dp_du: *dp_du, dp_dv: *dp_dv, geom: geom }
    }
    /// Setup the differential geometry using the normal passed for the surface normal
    pub fn with_normal(p: &Point, n: &Normal, dp_du: &Vector, dp_dv: &Vector,
               geom: &'a (Geometry + 'a))
               -> DifferentialGeometry<'a> {
        let nn = n.normalized();
        DifferentialGeometry { p: *p, n: nn, ng: nn,
                               dp_du: *dp_du, dp_dv: *dp_dv, geom: geom }
    }
}

<|endoftext|>


<commit_before>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(const_fn,lang_items)]

extern crate common;
extern crate drivers;
extern crate hil;
extern crate sam4l;
extern crate support;

use hil::Controller;
use hil::spi_master::SpiMaster;
use drivers::timer::AlarmToTimer;
use drivers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};

// HAL unit tests. To enable a particular unit test, uncomment
// the module here and uncomment the call to start the test in
// the init function below.
//mod gpio_dummy;
//mod spi_dummy;
//mod spi_driver;

#[allow(unused_variables,dead_code)]
pub struct DummyCB {
    val: u8
}

static mut spi_read_buf:  [u8;4] = [0; 4];
static mut spi_write_buf: [u8;4] = [0; 4];

pub struct Firestorm {
    chip: sam4l::chip::Sam4l,
    console: &'static drivers::console::Console<'static, sam4l::usart::USART>,
    gpio: drivers::gpio::GPIO<[&'static hil::gpio::GPIOPin; 13]>,
    timer: &'static drivers::timer::TimerDriver<'static, AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>>>,
    tmp006: &'static drivers::tmp006::TMP006<'static, sam4l::i2c::I2CDevice, sam4l::gpio::GPIOPin>,
    spi: &'static drivers::spi::Spi<'static, sam4l::spi::Spi>,
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    #[inline(never)]
    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {

        match driver_num {
            0 => f(Some(self.console)),
            1 => f(Some(&self.gpio)),
            2 => f(Some(self.tmp006)),
            3 => f(Some(self.timer)),
            4 => f(Some(self.spi)),
            _ => f(None)
        }
    }
}

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = mem::transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

pub unsafe fn init<'a>() -> &'a mut Firestorm {
    use core::mem;

    static_init!(console : drivers::console::Console<sam4l::usart::USART> =
                    drivers::console::Console::new(&sam4l::usart::USART3));
    sam4l::usart::USART3.set_client(console);

    let ast = &sam4l::ast::AST;

    static_init!(mux_alarm : MuxAlarm<'static, sam4l::ast::Ast> =
                    MuxAlarm::new(&sam4l::ast::AST));
    ast.configure(mux_alarm);

    // the i2c address of the device is 0x40
    static_init!(tmp006 : drivers::tmp006::TMP006<'static, sam4l::i2c::I2CDevice, sam4l::gpio::GPIOPin> =
                    drivers::tmp006::TMP006::new(&sam4l::i2c::I2C2, 0x40, &sam4l::gpio::PA[9]));
    sam4l::gpio::PA[9].set_client(tmp006);

    static_init!(virtual_alarm1 : VirtualMuxAlarm<'static, sam4l::ast::Ast> =
                    VirtualMuxAlarm::new(mux_alarm));
    static_init!(vtimer1 : AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>> =
                            AlarmToTimer::new(virtual_alarm1));
    virtual_alarm1.set_client(vtimer1);
    static_init!(timer : drivers::timer::TimerDriver<AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>>> =
                            drivers::timer::TimerDriver::new(vtimer1));
    vtimer1.set_client(timer);

    // Configure SPI pins: CLK, MISO, MOSI, CS3
    sam4l::gpio::PC[ 6].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 4].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 5].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 1].configure(Some(sam4l::gpio::PeripheralFunction::A));
    // Initialize and enable SPI HAL
    static_init!(spi: drivers::spi::Spi<'static, sam4l::spi::Spi> =
                      drivers::spi::Spi::new(&mut sam4l::spi::SPI));
    spi.config_buffers(&mut spi_read_buf, &mut spi_write_buf);

    static_init!(firestorm : Firestorm = Firestorm {
        chip: sam4l::chip::Sam4l::new(),
        console: &*console,
        gpio: drivers::gpio::GPIO::new(
            [ &sam4l::gpio::PC[10], &sam4l::gpio::PC[19]
            , &sam4l::gpio::PC[13], &sam4l::gpio::PA[17]
            , &sam4l::gpio::PC[20], &sam4l::gpio::PA[19]
            , &sam4l::gpio::PA[14], &sam4l::gpio::PA[16]
            , &sam4l::gpio::PA[13], &sam4l::gpio::PA[11]
            , &sam4l::gpio::PA[10], &sam4l::gpio::PA[12]
            , &sam4l::gpio::PC[09]]),
        timer: timer,
        tmp006: &*tmp006,
        spi: &*spi,
    });

    sam4l::usart::USART3.configure(sam4l::usart::USARTParams {
        //client: &console,
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });

    sam4l::gpio::PB[09].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PB[10].configure(Some(sam4l::gpio::PeripheralFunction::A));

    // Configure I2C SDA and SCL pins
    sam4l::gpio::PA[21].configure(Some(sam4l::gpio::PeripheralFunction::E));
    sam4l::gpio::PA[22].configure(Some(sam4l::gpio::PeripheralFunction::E));

    // Uncommenting the following line will cause the device to use the
    // SPI HAL to write [8, 7, 6, 5, 4, 3, 2, 1] once over the SPI then
    // echo the 8 bytes read from the slave continuously.
    //spi_dummy::spi_dummy_test();

    // Uncommenting the following line will toggle the LED whenever the value of
    // Firestorm's pin 8 changes value (e.g., connect a push button to pin 8 and
    // press toggle it).
    //gpio_dummy::gpio_dummy_test();

    sam4l::spi::SPI.set_active_peripheral(sam4l::spi::Peripheral::Peripheral1);
    sam4l::spi::SPI.init(spi as &hil::spi_master::SpiCallback);
    sam4l::spi::SPI.enable();

    firestorm.console.initialize();
    firestorm
}

use core::fmt::Arguments;

#[cfg(not(test))]
#[lang="panic_fmt"]
#[no_mangle]
pub unsafe extern fn rust_begin_unwind(_args: &Arguments,
    _file: &'static str, _line: usize) -> ! {
    use hil::uart::UART;
    use core::fmt::*;
    use support::nop;

    sam4l::usart::USART3.configure(sam4l::usart::USARTParams {
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });
    sam4l::usart::USART3.enable_tx();

    struct Writer;

    impl Write for Writer {
        fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
            unsafe {
                for c in s.bytes() {
                    sam4l::usart::USART3.send_byte(c);
                }
            }
            Ok(())
        }
    }

    let _ = Writer.write_fmt(format_args!("Kernel panic... Sorry!\r\n"));

    let led = &sam4l::gpio::PC[10];
    led.enable_output();
    loop {
        for _ in 0..1000000 {
            led.set();
            nop();
        }
        for _ in 0..1000000 {
            led.clear();
            nop();
        }
    }
}

<commit_msg>Restore kernel SPI buffer to 64 bytes.<commit_after>#![crate_name = "platform"]
#![crate_type = "rlib"]
#![no_std]
#![feature(const_fn,lang_items)]

extern crate common;
extern crate drivers;
extern crate hil;
extern crate sam4l;
extern crate support;

use hil::Controller;
use hil::spi_master::SpiMaster;
use drivers::timer::AlarmToTimer;
use drivers::virtual_alarm::{MuxAlarm, VirtualMuxAlarm};

// HAL unit tests. To enable a particular unit test, uncomment
// the module here and uncomment the call to start the test in
// the init function below.
//mod gpio_dummy;
//mod spi_dummy;
//mod spi_driver;

#[allow(unused_variables,dead_code)]
pub struct DummyCB {
    val: u8
}

static mut spi_read_buf:  [u8; 64] = [0; 64];
static mut spi_write_buf: [u8; 64] = [0; 64];

pub struct Firestorm {
    chip: sam4l::chip::Sam4l,
    console: &'static drivers::console::Console<'static, sam4l::usart::USART>,
    gpio: drivers::gpio::GPIO<[&'static hil::gpio::GPIOPin; 13]>,
    timer: &'static drivers::timer::TimerDriver<'static, AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>>>,
    tmp006: &'static drivers::tmp006::TMP006<'static, sam4l::i2c::I2CDevice, sam4l::gpio::GPIOPin>,
    spi: &'static drivers::spi::Spi<'static, sam4l::spi::Spi>,
}

impl Firestorm {
    pub unsafe fn service_pending_interrupts(&mut self) {
        self.chip.service_pending_interrupts()
    }

    pub unsafe fn has_pending_interrupts(&mut self) -> bool {
        self.chip.has_pending_interrupts()
    }

    #[inline(never)]
    pub fn with_driver<F, R>(&mut self, driver_num: usize, f: F) -> R where
            F: FnOnce(Option<&hil::Driver>) -> R {

        match driver_num {
            0 => f(Some(self.console)),
            1 => f(Some(&self.gpio)),
            2 => f(Some(self.tmp006)),
            3 => f(Some(self.timer)),
            4 => f(Some(self.spi)),
            _ => f(None)
        }
    }
}

macro_rules! static_init {
   ($V:ident : $T:ty = $e:expr) => {
        let $V : &mut $T = {
            // Waiting out for size_of to be available at compile-time to avoid
            // hardcoding an abitrary large size...
            static mut BUF : [u8; 1024] = [0; 1024];
            let mut tmp : &mut $T = mem::transmute(&mut BUF);
            *tmp = $e;
            tmp
        };
   }
}

pub unsafe fn init<'a>() -> &'a mut Firestorm {
    use core::mem;

    static_init!(console : drivers::console::Console<sam4l::usart::USART> =
                    drivers::console::Console::new(&sam4l::usart::USART3));
    sam4l::usart::USART3.set_client(console);

    let ast = &sam4l::ast::AST;

    static_init!(mux_alarm : MuxAlarm<'static, sam4l::ast::Ast> =
                    MuxAlarm::new(&sam4l::ast::AST));
    ast.configure(mux_alarm);

    // the i2c address of the device is 0x40
    static_init!(tmp006 : drivers::tmp006::TMP006<'static, sam4l::i2c::I2CDevice, sam4l::gpio::GPIOPin> =
                    drivers::tmp006::TMP006::new(&sam4l::i2c::I2C2, 0x40, &sam4l::gpio::PA[9]));
    sam4l::gpio::PA[9].set_client(tmp006);

    static_init!(virtual_alarm1 : VirtualMuxAlarm<'static, sam4l::ast::Ast> =
                    VirtualMuxAlarm::new(mux_alarm));
    static_init!(vtimer1 : AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>> =
                            AlarmToTimer::new(virtual_alarm1));
    virtual_alarm1.set_client(vtimer1);
    static_init!(timer : drivers::timer::TimerDriver<AlarmToTimer<'static,
                                VirtualMuxAlarm<'static, sam4l::ast::Ast>>> =
                            drivers::timer::TimerDriver::new(vtimer1));
    vtimer1.set_client(timer);

    // Configure SPI pins: CLK, MISO, MOSI, CS3
    sam4l::gpio::PC[ 6].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 4].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 5].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PC[ 1].configure(Some(sam4l::gpio::PeripheralFunction::A));
    // Initialize and enable SPI HAL
    static_init!(spi: drivers::spi::Spi<'static, sam4l::spi::Spi> =
                      drivers::spi::Spi::new(&mut sam4l::spi::SPI));
    spi.config_buffers(&mut spi_read_buf, &mut spi_write_buf);

    static_init!(firestorm : Firestorm = Firestorm {
        chip: sam4l::chip::Sam4l::new(),
        console: &*console,
        gpio: drivers::gpio::GPIO::new(
            [ &sam4l::gpio::PC[10], &sam4l::gpio::PC[19]
            , &sam4l::gpio::PC[13], &sam4l::gpio::PA[17]
            , &sam4l::gpio::PC[20], &sam4l::gpio::PA[19]
            , &sam4l::gpio::PA[14], &sam4l::gpio::PA[16]
            , &sam4l::gpio::PA[13], &sam4l::gpio::PA[11]
            , &sam4l::gpio::PA[10], &sam4l::gpio::PA[12]
            , &sam4l::gpio::PC[09]]),
        timer: timer,
        tmp006: &*tmp006,
        spi: &*spi,
    });

    sam4l::usart::USART3.configure(sam4l::usart::USARTParams {
        //client: &console,
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });

    sam4l::gpio::PB[09].configure(Some(sam4l::gpio::PeripheralFunction::A));
    sam4l::gpio::PB[10].configure(Some(sam4l::gpio::PeripheralFunction::A));

    // Configure I2C SDA and SCL pins
    sam4l::gpio::PA[21].configure(Some(sam4l::gpio::PeripheralFunction::E));
    sam4l::gpio::PA[22].configure(Some(sam4l::gpio::PeripheralFunction::E));

    // Uncommenting the following line will cause the device to use the
    // SPI HAL to write [8, 7, 6, 5, 4, 3, 2, 1] once over the SPI then
    // echo the 8 bytes read from the slave continuously.
    //spi_dummy::spi_dummy_test();

    // Uncommenting the following line will toggle the LED whenever the value of
    // Firestorm's pin 8 changes value (e.g., connect a push button to pin 8 and
    // press toggle it).
    //gpio_dummy::gpio_dummy_test();

    sam4l::spi::SPI.set_active_peripheral(sam4l::spi::Peripheral::Peripheral1);
    sam4l::spi::SPI.init(spi as &hil::spi_master::SpiCallback);
    sam4l::spi::SPI.enable();

    firestorm.console.initialize();
    firestorm
}

use core::fmt::Arguments;

#[cfg(not(test))]
#[lang="panic_fmt"]
#[no_mangle]
pub unsafe extern fn rust_begin_unwind(_args: &Arguments,
    _file: &'static str, _line: usize) -> ! {
    use hil::uart::UART;
    use core::fmt::*;
    use support::nop;

    sam4l::usart::USART3.configure(sam4l::usart::USARTParams {
        baud_rate: 115200,
        data_bits: 8,
        parity: hil::uart::Parity::None
    });
    sam4l::usart::USART3.enable_tx();

    struct Writer;

    impl Write for Writer {
        fn write_str(&mut self, s: &str) -> ::core::fmt::Result {
            unsafe {
                for c in s.bytes() {
                    sam4l::usart::USART3.send_byte(c);
                }
            }
            Ok(())
        }
    }

    let _ = Writer.write_fmt(format_args!("Kernel panic... Sorry!\r\n"));

    let led = &sam4l::gpio::PC[10];
    led.enable_output();
    loop {
        for _ in 0..1000000 {
            led.set();
            nop();
        }
        for _ in 0..1000000 {
            led.clear();
            nop();
        }
    }
}

<|endoftext|>


<commit_before>pub const POMBASE_ANN_EXT_TERM_CV_NAME: &'static str = "PomBase annotation extension terms";
pub const ANNOTATION_EXT_REL_PREFIX: &'static str = "annotation_extension_relation-";

pub const DB_NAME: &'static str = "PomBase";

pub enum FeatureRelAnnotationType {
    Interaction,
    Ortholog,
    Paralog,
}
pub struct FeatureRelConfig {
    pub rel_type_name: &'static str,
    pub annotation_type: FeatureRelAnnotationType,
}
pub const FEATURE_REL_CONFIGS: [FeatureRelConfig; 4] =
    [
        FeatureRelConfig {
            rel_type_name: "interacts_physically",
            annotation_type: FeatureRelAnnotationType::Interaction,
        },
        FeatureRelConfig {
            rel_type_name: "interacts_genetically",
            annotation_type: FeatureRelAnnotationType::Interaction,
        },
        FeatureRelConfig {
            rel_type_name: "orthologous_to",
            annotation_type: FeatureRelAnnotationType::Ortholog,
        },
        FeatureRelConfig {
            rel_type_name: "paralogous_to",
            annotation_type: FeatureRelAnnotationType::Paralog,
        },
    ];

// relations to use when copy annotation to parents (ie. adding the
// annotation of child terms to parents)
pub const DESCENDANT_REL_NAMES: [&'static str; 3] = ["is_a", "part_of", "regulates"];
// relationships where the more specific term is the object, used when reading cvtermpath
pub const INVERSE_REL_NAMES: [&'static str; 1] = ["has_part"];
// only consider inverse relations for these ontologies:
pub const INVERSE_REL_CV_NAMES: [&'static str; 1] = ["fission_yeast_phenotype"];

// number of genes before (and after) to add to the gene_neighbourhood field
pub const GENE_NEIGHBOURHOOD_DISTANCE: usize = 5;

// "interesting parents" are those stored in the JSON in the TermShort structs
#[derive(Clone)]
pub struct InterestingParent {
    pub termid: &'static str,
    pub rel_name: &'static str,
}

pub const TRANSCRIPT_FEATURE_TYPES: [&'static str; 6] =
    ["snRNA", "rRNA", "mRNA", "snoRNA", "ncRNA", "tRNA"];

// when creating a TermShort struct, for each of these termids if the term has
// an "interesting parent" using the given rel_name, we store it in the
// interesting_parents field of the TermShort
pub const INTERESTING_PARENTS: [InterestingParent; 3] = [
    InterestingParent {
        termid: "FYPO:0000002",
        rel_name: "is_a",
    },
    InterestingParent {
        termid: "FYPO:0000003",
        rel_name: "is_a",
    },

    // a with property on a protein binding (GO:0005515) is displayed
    // as a binds extension - configure this to allow easy checking for that in
    // process_feature_cvterms()
    // see: https://github.com/pombase/website/issues/108
    InterestingParent {
        termid: "GO:0005515",
        rel_name: "is_a",
    },
];
<commit_msg>Reorder the config defs slightly<commit_after>pub const POMBASE_ANN_EXT_TERM_CV_NAME: &'static str = "PomBase annotation extension terms";
pub const ANNOTATION_EXT_REL_PREFIX: &'static str = "annotation_extension_relation-";

pub const DB_NAME: &'static str = "PomBase";

pub enum FeatureRelAnnotationType {
    Interaction,
    Ortholog,
    Paralog,
}
pub struct FeatureRelConfig {
    pub rel_type_name: &'static str,
    pub annotation_type: FeatureRelAnnotationType,
}
pub const FEATURE_REL_CONFIGS: [FeatureRelConfig; 4] =
    [
        FeatureRelConfig {
            rel_type_name: "interacts_physically",
            annotation_type: FeatureRelAnnotationType::Interaction,
        },
        FeatureRelConfig {
            rel_type_name: "interacts_genetically",
            annotation_type: FeatureRelAnnotationType::Interaction,
        },
        FeatureRelConfig {
            rel_type_name: "orthologous_to",
            annotation_type: FeatureRelAnnotationType::Ortholog,
        },
        FeatureRelConfig {
            rel_type_name: "paralogous_to",
            annotation_type: FeatureRelAnnotationType::Paralog,
        },
    ];

// relations to use when copy annotation to parents (ie. adding the
// annotation of child terms to parents)
pub const DESCENDANT_REL_NAMES: [&'static str; 3] = ["is_a", "part_of", "regulates"];
// relationships where the more specific term is the object, used when reading cvtermpath
pub const INVERSE_REL_NAMES: [&'static str; 1] = ["has_part"];
// only consider inverse relations for these ontologies:
pub const INVERSE_REL_CV_NAMES: [&'static str; 1] = ["fission_yeast_phenotype"];

// number of genes before (and after) to add to the gene_neighbourhood field
pub const GENE_NEIGHBOURHOOD_DISTANCE: usize = 5;

pub const TRANSCRIPT_FEATURE_TYPES: [&'static str; 6] =
    ["snRNA", "rRNA", "mRNA", "snoRNA", "ncRNA", "tRNA"];

// "interesting parents" are those stored in the JSON in the TermShort structs
#[derive(Clone)]
pub struct InterestingParent {
    pub termid: &'static str,
    pub rel_name: &'static str,
}

// when creating a TermShort struct, for each of these termids if the term has
// an "interesting parent" using the given rel_name, we store it in the
// interesting_parents field of the TermShort
pub const INTERESTING_PARENTS: [InterestingParent; 3] = [
    InterestingParent {
        termid: "FYPO:0000002",
        rel_name: "is_a",
    },
    InterestingParent {
        termid: "FYPO:0000003",
        rel_name: "is_a",
    },

    // a with property on a protein binding (GO:0005515) is displayed
    // as a binds extension - configure this to allow easy checking for that in
    // process_feature_cvterms()
    // see: https://github.com/pombase/website/issues/108
    InterestingParent {
        termid: "GO:0005515",
        rel_name: "is_a",
    },
];
<|endoftext|>


<commit_before>use std::{
    io,
    net::{IpAddr, SocketAddr},
    time::Duration,
    path::PathBuf,
};

use tokio::{
    io::{AsyncReadExt, AsyncWriteExt},
    net::UnixStream,
    sync::mpsc,
};

use byteorder::{BigEndian, ByteOrder};
use futures::future;
use log::{debug, error, info};
use rand::Rng;
use trust_dns_proto::{
    op::{header::MessageType, response_code::ResponseCode, Message, Query},
    rr::{Name, RData, RecordType},
};

use crate::{
    config::{ConfigType, ServerConfig},
    context::SharedContext,
    relay::{
        loadbalancing::server::{PlainPingBalancer, ServerType},
        socks5::Address,
        sys::create_udp_socket,
        tcprelay::ProxyStream,
        utils::try_timeout,
    },
};

async fn stream_lookup<T>(qname: &Name, qtype: RecordType, stream: &mut T) -> io::Result<Message>
where
    T: AsyncReadExt + AsyncWriteExt + Unpin,
{
    let mut message = Message::new();
    let mut query = Query::new();

    query.set_query_type(qtype);
    query.set_name(qname.clone());

    let id = rand::thread_rng().gen();
    message.set_id(id);
    message.set_recursion_desired(true);
    message.add_query(query);

    let req_buffer = message.to_vec()?;
    let size = req_buffer.len();
    let mut send_buffer = vec![0; size + 2];

    BigEndian::write_u16(&mut send_buffer[0..2], size as u16);
    send_buffer[2..size + 2].copy_from_slice(&req_buffer[0..size]);
    stream.write_all(&send_buffer[0..size + 2]).await?;

    let mut res_buffer = vec![0; 2];
    stream.read_exact(&mut res_buffer[0..2]).await?;

    let size = BigEndian::read_u16(&res_buffer[0..2]) as usize;
    let mut res_buffer = vec![0; size];
    stream.read_exact(&mut res_buffer[0..size]).await?;

    Ok(Message::from_vec(&res_buffer)?)
}

async fn local_lookup(qname: &Name, qtype: RecordType, path: &PathBuf) -> io::Result<Message> {
    let mut stream = UnixStream::connect(path).await?;
    stream_lookup(qname, qtype, &mut stream).await
}

async fn proxy_lookup(
    context: SharedContext,
    svr_cfg: &ServerConfig,
    ns: &Address,
    qname: &Name,
    qtype: RecordType,
) -> io::Result<Message> {
    let mut stream = ProxyStream::connect_proxied(context, svr_cfg, ns).await?;
    stream_lookup(qname, qtype, &mut stream).await
}

async fn acl_lookup(
    context: SharedContext,
    svr_cfg: &ServerConfig,
    local: &PathBuf,
    remote: &Address,
    qname: &Name,
    qtype: RecordType,
) -> io::Result<Message> {
    // Start querying name servers
    debug!(
        "attempting lookup of {:?} {} with ns {:?} and {:?}",
        qtype, qname, local, remote
    );

    let timeout = Some(Duration::new(3, 0));
    let local_response_fut = try_timeout(local_lookup(qname, qtype, local), timeout);

    let timeout = Some(Duration::new(3, 0));
    let remote_response_fut = try_timeout(proxy_lookup(context.clone(), svr_cfg, remote, qname, qtype), timeout);

    let (local_response, remote_response) = future::join(local_response_fut, remote_response_fut).await;
    let local_response = local_response.unwrap_or_else(|_| Message::new());
    let remote_response = remote_response.unwrap_or_else(|_| Message::new());

    // remove the last dot from fqdn name
    let mut name = qname.to_ascii();
    name.pop();
    let addr = Address::DomainNameAddress(name, 0);
    let qname_in_proxy_list = context.check_qname_in_proxy_list(&addr).await;

    let mut ip_bypassed = false;
    for rec in local_response.answers() {
        let bypassed = match rec.rdata() {
            RData::A(ref ip) => {
                let addr = Address::SocketAddress(SocketAddr::new(IpAddr::from(*ip), 0));
                context.check_target_bypassed(&addr).await
            }
            RData::AAAA(ref ip) => {
                let addr = Address::SocketAddress(SocketAddr::new(IpAddr::from(*ip), 0));
                context.check_target_bypassed(&addr).await
            }
            _ => false,
        };
        if bypassed {
            ip_bypassed = true;
        }
    }

    if local_response.answer_count() == 0 {
        return Ok(remote_response.clone());
    }

    if remote_response.answer_count() == 0 {
        return Ok(local_response.clone());
    }

    if qname_in_proxy_list {
        debug!("pick remote response (qname): {:?}", remote_response);
        Ok(remote_response.clone())
    } else if !ip_bypassed {
        debug!("pick remote response (ip): {:?}", remote_response);
        Ok(remote_response.clone())
    } else {
        debug!("pick DNS local response: {:?}", local_response);
        Ok(local_response.clone())
    }
}

/// Start a DNS relay local server
pub async fn run(context: SharedContext) -> io::Result<()> {
    let local_addr = match context.config().config_type {
        ConfigType::DnsLocal => {
            // Standalone server
            context.config().local_addr.as_ref().expect("local config")
        }
        #[cfg(feature = "local-dns-relay")]
        c if c.is_local() => {
            // Integrated mode
            context.config().dns_local_addr.as_ref().expect("dns relay addr")
        }
        _ => {
            panic!("ConfigType must be DnsLocal");
        }
    };

    let bind_addr = local_addr.bind_addr(&context).await?;

    let socket = create_udp_socket(&bind_addr).await?;

    let actual_local_addr = socket.local_addr()?;
    info!("shadowsocks DNS relay listening on {}", actual_local_addr);

    let (mut rx, mut tx) = socket.split();
    let (qtx, mut qrx) = mpsc::channel::<(SocketAddr, Vec<u8>)>(1024);

    tokio::spawn(async move {
        while let Some((src, pkt)) = qrx.recv().await {
            if let Err(err) = tx.send_to(&pkt, &src).await {
                error!("failed to send packet {} bytes to {}, error: {}", pkt.len(), src, err);
            }
        }
    });

    // FIXME: We use TCP to send remote queries by default, which should be configuable.
    let balancer = PlainPingBalancer::new(context.clone(), ServerType::Tcp).await;

    loop {
        let mut req_buffer: [u8; 512] = [0; 512];
        let (_, src) = match rx.recv_from(&mut req_buffer).await {
            Ok(x) => x,
            Err(e) => {
                error!("DNS relay read from UDP socket error: {}", e);
                continue;
            }
        };

        let request = match Message::from_vec(&req_buffer) {
            Ok(x) => x,
            Err(e) => {
                error!("failed to parse UDP query message, error: {:?}", e);
                continue;
            }
        };

        debug!("received src: {}, query: {:?}", src, request);

        let context = context.clone();
        let mut qtx = qtx.clone();
        let server = balancer.pick_server();

        tokio::spawn(async move {
            let mut message = Message::new();
            message.set_id(request.id());
            message.set_recursion_desired(true);
            message.set_recursion_available(true);
            message.set_message_type(MessageType::Response);

            if request.queries().is_empty() {
                message.set_response_code(ResponseCode::FormErr);
            } else {
                let config = context.config();
                let local_path = config.local_dns_path.as_ref().expect("local query DNS address");
                let remote_addr = config.remote_dns_addr.as_ref().expect("remote query DNS address");

                let question = &request.queries()[0];

                let qname = question.name();
                let qtype = question.query_type();
                let svr_cfg = server.server_config();

                let r = acl_lookup(context.clone(), svr_cfg, &local_path, &remote_addr, qname, qtype).await;

                if let Ok(result) = r {
                    #[cfg(feature = "local-dns-relay")]
                    for rec in result.answers() {
                        debug!("dns answer: {:?}", rec);

                        // Remove the last dot in fqdn name
                        let mut name = question.name().to_ascii();
                        name.pop();

                        match rec.rdata() {
                            RData::A(ref ip) => context.add_to_reverse_lookup_cache(IpAddr::from(*ip), name),
                            RData::AAAA(ref ip) => context.add_to_reverse_lookup_cache(IpAddr::from(*ip), name),
                            _ => (),
                        }
                    }

                    message = result;
                    message.set_id(request.id());
                } else {
                    message.set_response_code(ResponseCode::ServFail);
                }
            }

            debug!("DNS src: {}, final response: {:?}", src, message);

            match message.to_vec() {
                Err(err) => {
                    error!("failed to serialize message, error: {}", err);
                }
                Ok(res_buffer) => {
                    if let Err(..) = qtx.send((src, res_buffer)).await {
                        error!("DNS send back queue is closed unexpectly");
                    }
                }
            }
        });
    }
}
<commit_msg>Only enable unix domain DNS resolver on Android<commit_after>use std::{
    io,
    net::{IpAddr, SocketAddr},
    time::Duration,
};

use tokio::{
    io::{AsyncReadExt, AsyncWriteExt},
    sync::mpsc,
};

#[cfg(target_os = "android")]
use std::path::PathBuf;
#[cfg(target_os = "android")]
use tokio::net::UnixStream;

#[cfg(not(target_os = "android"))]
use tokio::net::UdpSocket;
#[cfg(not(target_os = "android"))]
use std::net::{Ipv4Addr, SocketAddrV4};

use byteorder::{BigEndian, ByteOrder};
use futures::future;
use log::{debug, error, info};
use rand::Rng;
use trust_dns_proto::{
    op::{header::MessageType, response_code::ResponseCode, Message, Query},
    rr::{Name, RData, RecordType},
};

use crate::{
    config::{ConfigType, ServerConfig},
    context::SharedContext,
    relay::{
        loadbalancing::server::{PlainPingBalancer, ServerType},
        socks5::Address,
        sys::create_udp_socket,
        tcprelay::ProxyStream,
        utils::try_timeout,
    },
};

async fn stream_lookup<T>(qname: &Name, qtype: RecordType, stream: &mut T) -> io::Result<Message>
where
    T: AsyncReadExt + AsyncWriteExt + Unpin,
{
    let mut message = Message::new();
    let mut query = Query::new();

    query.set_query_type(qtype);
    query.set_name(qname.clone());

    let id = rand::thread_rng().gen();
    message.set_id(id);
    message.set_recursion_desired(true);
    message.add_query(query);

    let req_buffer = message.to_vec()?;
    let size = req_buffer.len();
    let mut send_buffer = vec![0; size + 2];

    BigEndian::write_u16(&mut send_buffer[0..2], size as u16);
    send_buffer[2..size + 2].copy_from_slice(&req_buffer[0..size]);
    stream.write_all(&send_buffer[0..size + 2]).await?;

    let mut res_buffer = vec![0; 2];
    stream.read_exact(&mut res_buffer[0..2]).await?;

    let size = BigEndian::read_u16(&res_buffer[0..2]) as usize;
    let mut res_buffer = vec![0; size];
    stream.read_exact(&mut res_buffer[0..size]).await?;

    Ok(Message::from_vec(&res_buffer)?)
}

#[cfg(target_os = "android")]
async fn local_lookup(qname: &Name, qtype: RecordType, path: &PathBuf) -> io::Result<Message> {
    let mut stream = UnixStream::connect(path).await?;
    stream_lookup(qname, qtype, &mut stream).await
}

#[cfg(not(target_os = "android"))]
async fn local_lookup(qname: &Name, qtype: RecordType, server: &SocketAddr) -> io::Result<Message> {
    let bind_addr = SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 0));
    let mut socket = UdpSocket::bind(bind_addr).await?;

    let mut message = Message::new();
    let mut query = Query::new();

    query.set_query_type(qtype);
    query.set_name(qname.clone());

    let id = rand::thread_rng().gen();
    message.set_id(id);
    message.set_recursion_desired(true);
    message.add_query(query);

    let req_buffer = message.to_vec()?;
    socket.send_to(&req_buffer, server).await?;

    let mut res_buffer = vec![0; 512];
    socket.recv_from(&mut res_buffer).await?;

    Ok(Message::from_vec(&res_buffer)?)
}

async fn proxy_lookup(
    context: SharedContext,
    svr_cfg: &ServerConfig,
    ns: &Address,
    qname: &Name,
    qtype: RecordType,
) -> io::Result<Message> {
    let mut stream = ProxyStream::connect_proxied(context, svr_cfg, ns).await?;
    stream_lookup(qname, qtype, &mut stream).await
}

async fn acl_lookup(
    context: SharedContext,
    svr_cfg: &ServerConfig,
    #[cfg(target_os = "android")]
    local: &PathBuf,
    #[cfg(not(target_os = "android"))]
    local: &SocketAddr,
    remote: &Address,
    qname: &Name,
    qtype: RecordType,
) -> io::Result<Message> {
    // Start querying name servers
    debug!(
        "attempting lookup of {:?} {} with ns {:?} and {:?}",
        qtype, qname, local, remote
    );

    let timeout = Some(Duration::new(3, 0));
    let local_response_fut = try_timeout(local_lookup(qname, qtype, local), timeout);

    let timeout = Some(Duration::new(3, 0));
    let remote_response_fut = try_timeout(proxy_lookup(context.clone(), svr_cfg, remote, qname, qtype), timeout);

    let (local_response, remote_response) = future::join(local_response_fut, remote_response_fut).await;
    let local_response = local_response.unwrap_or_else(|_| Message::new());
    let remote_response = remote_response.unwrap_or_else(|_| Message::new());

    // remove the last dot from fqdn name
    let mut name = qname.to_ascii();
    name.pop();
    let addr = Address::DomainNameAddress(name, 0);
    let qname_in_proxy_list = context.check_qname_in_proxy_list(&addr).await;

    let mut ip_bypassed = false;
    for rec in local_response.answers() {
        let bypassed = match rec.rdata() {
            RData::A(ref ip) => {
                let addr = Address::SocketAddress(SocketAddr::new(IpAddr::from(*ip), 0));
                context.check_target_bypassed(&addr).await
            }
            RData::AAAA(ref ip) => {
                let addr = Address::SocketAddress(SocketAddr::new(IpAddr::from(*ip), 0));
                context.check_target_bypassed(&addr).await
            }
            _ => false,
        };
        if bypassed {
            ip_bypassed = true;
        }
    }

    if local_response.answer_count() == 0 {
        return Ok(remote_response.clone());
    }

    if remote_response.answer_count() == 0 {
        return Ok(local_response.clone());
    }

    if qname_in_proxy_list {
        debug!("pick remote response (qname): {:?}", remote_response);
        Ok(remote_response.clone())
    } else if !ip_bypassed {
        debug!("pick remote response (ip): {:?}", remote_response);
        Ok(remote_response.clone())
    } else {
        debug!("pick DNS local response: {:?}", local_response);
        Ok(local_response.clone())
    }
}

/// Start a DNS relay local server
pub async fn run(context: SharedContext) -> io::Result<()> {
    let local_addr = match context.config().config_type {
        ConfigType::DnsLocal => {
            // Standalone server
            context.config().local_addr.as_ref().expect("local config")
        }
        #[cfg(feature = "local-dns-relay")]
        c if c.is_local() => {
            // Integrated mode
            context.config().dns_local_addr.as_ref().expect("dns relay addr")
        }
        _ => {
            panic!("ConfigType must be DnsLocal");
        }
    };

    let bind_addr = local_addr.bind_addr(&context).await?;

    let socket = create_udp_socket(&bind_addr).await?;

    let actual_local_addr = socket.local_addr()?;
    info!("shadowsocks DNS relay listening on {}", actual_local_addr);

    let (mut rx, mut tx) = socket.split();
    let (qtx, mut qrx) = mpsc::channel::<(SocketAddr, Vec<u8>)>(1024);

    tokio::spawn(async move {
        while let Some((src, pkt)) = qrx.recv().await {
            if let Err(err) = tx.send_to(&pkt, &src).await {
                error!("failed to send packet {} bytes to {}, error: {}", pkt.len(), src, err);
            }
        }
    });

    // FIXME: We use TCP to send remote queries by default, which should be configuable.
    let balancer = PlainPingBalancer::new(context.clone(), ServerType::Tcp).await;

    loop {
        let mut req_buffer: [u8; 512] = [0; 512];
        let (_, src) = match rx.recv_from(&mut req_buffer).await {
            Ok(x) => x,
            Err(e) => {
                error!("DNS relay read from UDP socket error: {}", e);
                continue;
            }
        };

        let request = match Message::from_vec(&req_buffer) {
            Ok(x) => x,
            Err(e) => {
                error!("failed to parse UDP query message, error: {:?}", e);
                continue;
            }
        };

        debug!("received src: {}, query: {:?}", src, request);

        let context = context.clone();
        let mut qtx = qtx.clone();
        let server = balancer.pick_server();

        tokio::spawn(async move {
            let mut message = Message::new();
            message.set_id(request.id());
            message.set_recursion_desired(true);
            message.set_recursion_available(true);
            message.set_message_type(MessageType::Response);

            if request.queries().is_empty() {
                message.set_response_code(ResponseCode::FormErr);
            } else {
                let config = context.config();

                #[cfg(target_os = "android")]
                let local_addr = config.local_dns_path.as_ref().expect("local query DNS path");
                #[cfg(not(target_os = "android"))]
                let local_addr = config.local_dns_addr.as_ref().expect("local query DNS address");

                let remote_addr = config.remote_dns_addr.as_ref().expect("remote query DNS address");

                let question = &request.queries()[0];

                let qname = question.name();
                let qtype = question.query_type();
                let svr_cfg = server.server_config();

                let r = acl_lookup(context.clone(), svr_cfg, &local_addr, &remote_addr, qname, qtype).await;

                if let Ok(result) = r {
                    #[cfg(feature = "local-dns-relay")]
                    for rec in result.answers() {
                        debug!("dns answer: {:?}", rec);

                        // Remove the last dot in fqdn name
                        let mut name = question.name().to_ascii();
                        name.pop();

                        match rec.rdata() {
                            RData::A(ref ip) => context.add_to_reverse_lookup_cache(IpAddr::from(*ip), name),
                            RData::AAAA(ref ip) => context.add_to_reverse_lookup_cache(IpAddr::from(*ip), name),
                            _ => (),
                        }
                    }

                    message = result;
                    message.set_id(request.id());
                } else {
                    message.set_response_code(ResponseCode::ServFail);
                }
            }

            debug!("DNS src: {}, final response: {:?}", src, message);

            match message.to_vec() {
                Err(err) => {
                    error!("failed to serialize message, error: {}", err);
                }
                Ok(res_buffer) => {
                    if let Err(..) = qtx.send((src, res_buffer)).await {
                        error!("DNS send back queue is closed unexpectly");
                    }
                }
            }
        });
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use rocket_contrib::JSON;

#[get("/health", format = "application/json")]
pub fn health() -> JSON<HashMap<&'static str, &'static str>> {
    JSON(map!{
        "status" => "200",
        "detail" => "OK",
    })
}
<commit_msg>test: add test for health check<commit_after>use std::collections::HashMap;

use rocket_contrib::JSON;

#[get("/health", format = "application/json")]
pub fn health() -> JSON<HashMap<&'static str, &'static str>> {
    JSON(map!{
        "status" => "200",
        "detail" => "OK",
    })
}

#[cfg(test)]
mod tests {
    use rocket;
    use rocket::http::Status;
    use rocket::http::Method::*;
    use rocket::testing::MockRequest;

    use super::*;

    #[test]
    fn test_health() {
        let server = rocket::ignite().mount("/", routes![health]);
        let mut req = MockRequest::new(Get, "/health");
        let res = req.dispatch_with(&server);

        assert_eq!(res.status(), Status::Ok);
    }
}
<|endoftext|>


<commit_before>// 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 std::cmp;
use std::slice;

#[deriving(Copy)]
pub enum BufferResult {
    BufferUnderflow,
    BufferOverflow
}

pub trait ReadBuffer {
    fn is_empty(&self) -> bool;
    fn is_full(&self) -> bool;
    fn remaining(&self) -> uint;
    fn capacity(&self) -> uint;
    fn position(&self) -> uint { self.capacity() - self.remaining() }

    fn rewind(&mut self, distance: uint);
    fn truncate(&mut self, amount: uint);
    fn reset(&mut self);

    fn peek_next<'a>(&'a self, count: uint) -> &'a [u8];
    fn peek_remaining<'a>(&'a self) -> &'a [u8] {
        self.peek_next(self.remaining())
    }

    fn take_next<'a>(&'a mut self, count: uint) -> &'a [u8];
    fn take_remaining<'a>(&'a mut self) -> &'a [u8] {
        let rem = self.remaining();
        self.take_next(rem)
    }

    fn push_to<W: WriteBuffer>(&mut self, output: &mut W) {
        let count = cmp::min(output.remaining(), self.remaining());
        slice::bytes::copy_memory(output.take_next(count), self.take_next(count));
    }
}

pub trait WriteBuffer {
    fn is_empty(&self) -> bool;
    fn is_full(&self) -> bool;
    fn remaining(&self) -> uint;
    fn capacity(&self) -> uint;
    fn position(&self) -> uint { self.capacity() - self.remaining() }

    fn rewind(&mut self, distance: uint);
    fn reset(&mut self);

    // FIXME - Shouldn't need mut self
    fn peek_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a>;

    fn take_next<'a>(&'a mut self, count: uint) -> &'a mut [u8];
    fn take_remaining<'a>(&'a mut self) -> &'a mut [u8] {
        let rem = self.remaining();
        self.take_next(rem)
    }
    fn take_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a>;
}

pub struct RefReadBuffer<'a> {
    buff: &'a [u8],
    pos: uint
}

impl <'a> RefReadBuffer<'a> {
    pub fn new<'a>(buff: &'a [u8]) -> RefReadBuffer<'a> {
        RefReadBuffer {
            buff: buff,
            pos: 0
        }
    }
}

impl <'a> ReadBuffer for RefReadBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == self.buff.len() }
    fn is_full(&self) -> bool { self.pos == 0 }
    fn remaining(&self) -> uint { self.buff.len() - self.pos }
    fn capacity(&self) -> uint { self.buff.len() }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn truncate(&mut self, amount: uint) {
        self.buff = self.buff[..self.buff.len() - amount];
    }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_next<'a>(&'a self, count: uint) -> &'a [u8] { self.buff[self.pos..count] }

    fn take_next<'a>(&'a mut self, count: uint) -> &'a [u8] {
        let r = self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
}

pub struct OwnedReadBuffer {
    buff: Vec<u8>,
    len: uint,
    pos: uint
}

impl OwnedReadBuffer {
    pub fn new(buff: Vec<u8>) -> OwnedReadBuffer {
        let len = buff.len();
        OwnedReadBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn new_with_len<'a>(buff: Vec<u8>, len: uint) -> OwnedReadBuffer {
        OwnedReadBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn into_write_buffer(self) -> OwnedWriteBuffer {
        OwnedWriteBuffer::new(self.buff)
    }
    pub fn borrow_write_buffer<'a>(&'a mut self) -> BorrowedWriteBuffer<'a> {
        self.pos = 0;
        self.len = 0;
        BorrowedWriteBuffer::new(self)
    }
}

impl ReadBuffer for OwnedReadBuffer {
    fn is_empty(&self) -> bool { self.pos == self.len }
    fn is_full(&self) -> bool { self.pos == 0 }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn truncate(&mut self, amount: uint) { self.len -= amount; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_next<'a>(&'a self, count: uint) -> &'a [u8] { self.buff[self.pos..count] }

    fn take_next<'a>(&'a mut self, count: uint) -> &'a [u8] {
        let r = self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
}

pub struct RefWriteBuffer<'a> {
    buff: &'a mut [u8],
    len: uint,
    pos: uint
}

impl <'a> RefWriteBuffer<'a> {
    pub fn new<'a>(buff: &'a mut [u8]) -> RefWriteBuffer<'a> {
        let len = buff.len();
        RefWriteBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
}

impl <'a> WriteBuffer for RefWriteBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        RefReadBuffer::new(self.buff[mut ..self.pos])
    }

    fn take_next<'a>(&'a mut self, count: uint) -> &'a mut [u8] {
        let r = self.buff[mut self.pos..self.pos + count];
        self.pos += count;
        r
    }
    fn take_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        let r = RefReadBuffer::new(self.buff[mut ..self.pos]);
        self.pos = 0;
        r
    }
}

pub struct BorrowedWriteBuffer<'a> {
    parent: &'a mut OwnedReadBuffer,
    pos: uint,
    len: uint
}

impl <'a> BorrowedWriteBuffer<'a> {
    fn new<'a>(parent: &'a mut OwnedReadBuffer) -> BorrowedWriteBuffer<'a> {
        let buff_len = parent.buff.len();
        BorrowedWriteBuffer {
            parent: parent,
            pos: 0,
            len: buff_len
        }
    }
}

impl <'a> WriteBuffer for BorrowedWriteBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) {
        self.pos -= distance;
        self.parent.len -= distance;
    }
    fn reset(&mut self) {
        self.pos = 0;
        self.parent.len = 0;
    }

    fn peek_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        RefReadBuffer::new(self.parent.buff[..self.pos])
    }

    fn take_next<'a>(&'a mut self, count: uint) -> &'a mut [u8] {
        let r = self.parent.buff[mut self.pos..self.pos + count];
        self.pos += count;
        self.parent.len += count;
        r
    }
    fn take_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        let r = RefReadBuffer::new(self.parent.buff[..self.pos]);
        self.pos = 0;
        self.parent.len = 0;
        r
    }
}

pub struct OwnedWriteBuffer {
    buff: Vec<u8>,
    len: uint,
    pos: uint
}

impl OwnedWriteBuffer {
    pub fn new(buff: Vec<u8>) -> OwnedWriteBuffer {
        let len = buff.len();
        OwnedWriteBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn into_read_buffer(self) -> OwnedReadBuffer {
        let pos = self.pos;
        OwnedReadBuffer::new_with_len(self.buff, pos)
    }
}

impl WriteBuffer for OwnedWriteBuffer {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        RefReadBuffer::new(self.buff[..self.pos])
    }

    fn take_next<'a>(&'a mut self, count: uint) -> &'a mut [u8] {
        let r = self.buff[mut self.pos..self.pos + count];
        self.pos += count;
        r
    }
    fn take_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        let r = RefReadBuffer::new(self.buff[..self.pos]);
        self.pos = 0;
        r
    }
}
<commit_msg>Fix `shadowed lifetimes` warnings ...<commit_after>// 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 std::cmp;
use std::slice;

#[deriving(Copy)]
pub enum BufferResult {
    BufferUnderflow,
    BufferOverflow
}

pub trait ReadBuffer {
    fn is_empty(&self) -> bool;
    fn is_full(&self) -> bool;
    fn remaining(&self) -> uint;
    fn capacity(&self) -> uint;
    fn position(&self) -> uint { self.capacity() - self.remaining() }

    fn rewind(&mut self, distance: uint);
    fn truncate(&mut self, amount: uint);
    fn reset(&mut self);

    fn peek_next(&self, count: uint) -> &[u8];
    fn peek_remaining(&self) -> &[u8] {
        self.peek_next(self.remaining())
    }

    fn take_next(&mut self, count: uint) -> &[u8];
    fn take_remaining(&mut self) -> &[u8] {
        let rem = self.remaining();
        self.take_next(rem)
    }

    fn push_to<W: WriteBuffer>(&mut self, output: &mut W) {
        let count = cmp::min(output.remaining(), self.remaining());
        slice::bytes::copy_memory(output.take_next(count), self.take_next(count));
    }
}

pub trait WriteBuffer {
    fn is_empty(&self) -> bool;
    fn is_full(&self) -> bool;
    fn remaining(&self) -> uint;
    fn capacity(&self) -> uint;
    fn position(&self) -> uint { self.capacity() - self.remaining() }

    fn rewind(&mut self, distance: uint);
    fn reset(&mut self);

    // FIXME - Shouldn't need mut self
    fn peek_read_buffer(&mut self) -> RefReadBuffer;

    fn take_next(&mut self, count: uint) -> &mut [u8];
    fn take_remaining(&mut self) -> &mut [u8] {
        let rem = self.remaining();
        self.take_next(rem)
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer;
}

pub struct RefReadBuffer<'a> {
    buff: &'a [u8],
    pos: uint
}

impl <'a> RefReadBuffer<'a> {
    pub fn new(buff: &[u8]) -> RefReadBuffer {
        RefReadBuffer {
            buff: buff,
            pos: 0
        }
    }
}

impl <'a> ReadBuffer for RefReadBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == self.buff.len() }
    fn is_full(&self) -> bool { self.pos == 0 }
    fn remaining(&self) -> uint { self.buff.len() - self.pos }
    fn capacity(&self) -> uint { self.buff.len() }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn truncate(&mut self, amount: uint) {
        self.buff = self.buff[..self.buff.len() - amount];
    }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_next(&self, count: uint) -> &[u8] { self.buff[self.pos..count] }

    fn take_next(&mut self, count: uint) -> &[u8] {
        let r = self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
}

pub struct OwnedReadBuffer {
    buff: Vec<u8>,
    len: uint,
    pos: uint
}

impl OwnedReadBuffer {
    pub fn new(buff: Vec<u8>) -> OwnedReadBuffer {
        let len = buff.len();
        OwnedReadBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn new_with_len<'a>(buff: Vec<u8>, len: uint) -> OwnedReadBuffer {
        OwnedReadBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn into_write_buffer(self) -> OwnedWriteBuffer {
        OwnedWriteBuffer::new(self.buff)
    }
    pub fn borrow_write_buffer(&mut self) -> BorrowedWriteBuffer {
        self.pos = 0;
        self.len = 0;
        BorrowedWriteBuffer::new(self)
    }
}

impl ReadBuffer for OwnedReadBuffer {
    fn is_empty(&self) -> bool { self.pos == self.len }
    fn is_full(&self) -> bool { self.pos == 0 }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn truncate(&mut self, amount: uint) { self.len -= amount; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_next(&self, count: uint) -> &[u8] { self.buff[self.pos..count] }

    fn take_next(&mut self, count: uint) -> &[u8] {
        let r = self.buff[self.pos..self.pos + count];
        self.pos += count;
        r
    }
}

pub struct RefWriteBuffer<'a> {
    buff: &'a mut [u8],
    len: uint,
    pos: uint
}

impl <'a> RefWriteBuffer<'a> {
    pub fn new(buff: &mut [u8]) -> RefWriteBuffer {
        let len = buff.len();
        RefWriteBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
}

impl <'a> WriteBuffer for RefWriteBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_read_buffer(&mut self) -> RefReadBuffer {
        RefReadBuffer::new(self.buff[mut ..self.pos])
    }

    fn take_next(&mut self, count: uint) -> &mut [u8] {
        let r = self.buff[mut self.pos..self.pos + count];
        self.pos += count;
        r
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer {
        let r = RefReadBuffer::new(self.buff[mut ..self.pos]);
        self.pos = 0;
        r
    }
}

pub struct BorrowedWriteBuffer<'a> {
    parent: &'a mut OwnedReadBuffer,
    pos: uint,
    len: uint
}

impl <'a> BorrowedWriteBuffer<'a> {
    fn new(parent: &mut OwnedReadBuffer) -> BorrowedWriteBuffer {
        let buff_len = parent.buff.len();
        BorrowedWriteBuffer {
            parent: parent,
            pos: 0,
            len: buff_len
        }
    }
}

impl <'a> WriteBuffer for BorrowedWriteBuffer<'a> {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) {
        self.pos -= distance;
        self.parent.len -= distance;
    }
    fn reset(&mut self) {
        self.pos = 0;
        self.parent.len = 0;
    }

    fn peek_read_buffer(&mut self) -> RefReadBuffer {
        RefReadBuffer::new(self.parent.buff[..self.pos])
    }

    fn take_next<>(&mut self, count: uint) -> &mut [u8] {
        let r = self.parent.buff[mut self.pos..self.pos + count];
        self.pos += count;
        self.parent.len += count;
        r
    }
    fn take_read_buffer(&mut self) -> RefReadBuffer {
        let r = RefReadBuffer::new(self.parent.buff[..self.pos]);
        self.pos = 0;
        self.parent.len = 0;
        r
    }
}

pub struct OwnedWriteBuffer {
    buff: Vec<u8>,
    len: uint,
    pos: uint
}

impl OwnedWriteBuffer {
    pub fn new(buff: Vec<u8>) -> OwnedWriteBuffer {
        let len = buff.len();
        OwnedWriteBuffer {
            buff: buff,
            len: len,
            pos: 0
        }
    }
    pub fn into_read_buffer(self) -> OwnedReadBuffer {
        let pos = self.pos;
        OwnedReadBuffer::new_with_len(self.buff, pos)
    }
}

impl WriteBuffer for OwnedWriteBuffer {
    fn is_empty(&self) -> bool { self.pos == 0 }
    fn is_full(&self) -> bool { self.pos == self.len }
    fn remaining(&self) -> uint { self.len - self.pos }
    fn capacity(&self) -> uint { self.len }

    fn rewind(&mut self, distance: uint) { self.pos -= distance; }
    fn reset(&mut self) { self.pos = 0; }

    fn peek_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        RefReadBuffer::new(self.buff[..self.pos])
    }

    fn take_next<'a>(&'a mut self, count: uint) -> &'a mut [u8] {
        let r = self.buff[mut self.pos..self.pos + count];
        self.pos += count;
        r
    }
    fn take_read_buffer<'a>(&'a mut self) -> RefReadBuffer<'a> {
        let r = RefReadBuffer::new(self.buff[..self.pos]);
        self.pos = 0;
        r
    }
}
<|endoftext|>


<commit_before>//! The `status` subcommand, which shows `git status -s` for all known repos.

use std::io::{Write, stderr};

use git2;

use core::{GitGlobalResult, get_repos};
use errors::Result;

fn get_short_format_status(path: &str, status: git2::Status) -> String {
    // From git2's examples/status.rs...
    let mut istatus = match status {
        s if s.contains(git2::STATUS_INDEX_NEW) => 'A',
        s if s.contains(git2::STATUS_INDEX_MODIFIED) => 'M',
        s if s.contains(git2::STATUS_INDEX_DELETED) => 'D',
        s if s.contains(git2::STATUS_INDEX_RENAMED) => 'R',
        s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => 'T',
        _ => ' ',
    };
    let mut wstatus = match status {
        s if s.contains(git2::STATUS_WT_NEW) => {
            if istatus == ' ' { istatus = '?'; } '?'
        }
        s if s.contains(git2::STATUS_WT_MODIFIED) => 'M',
        s if s.contains(git2::STATUS_WT_DELETED) => 'D',
        s if s.contains(git2::STATUS_WT_RENAMED) => 'R',
        s if s.contains(git2::STATUS_WT_TYPECHANGE) => 'T',
        _ => ' ',
    };
    if status.contains(git2::STATUS_IGNORED) {
        istatus = '!';
        wstatus = '!';
    }
    // TODO: handle submodule statuses?
    format!("{}{} {}", istatus, wstatus, path)
}

pub fn get_results() -> Result<GitGlobalResult> {
    let repos = get_repos();
    let mut result = GitGlobalResult::new(&repos);
    result.pad_repo_output();
    for repo in repos.iter() {
        let git2_repo = match repo.as_git2_repo() {
            None => {
                writeln!(&mut stderr(),
                    "Could not open {} as a git repo. Perhaps you should run \
                    `git global scan` again.", repo
                ).expect("failed to write to STDERR");
                continue;
            }
            Some(repo) => repo,
        };
        let mut opts = git2::StatusOptions::new();
        opts.show(git2::StatusShow::IndexAndWorkdir)
            .include_ignored(false);
        let statuses = git2_repo.statuses(Some(&mut opts))
            .expect(&format!("Could not get statuses for {}.", repo));
        for entry in statuses.iter() {
            let path = entry.path().unwrap();
            let status = entry.status();
            let status_for_path = get_short_format_status(path, status);
            result.add_repo_message(repo, format!("{}", status_for_path));
        }
    }
    Ok(result)
}
<commit_msg>Spawn a thread to collect each repo's status.<commit_after>//! The `status` subcommand, which shows `git status -s` for all known repos.

use std::io::{Write, stderr};
use std::sync::{Arc, mpsc};
use std::thread;

use git2;

use core::{GitGlobalResult, Repo, get_repos};
use errors::Result;

fn get_short_format_status(path: &str, status: git2::Status) -> String {
    // From git2's examples/status.rs...
    let mut istatus = match status {
        s if s.contains(git2::STATUS_INDEX_NEW) => 'A',
        s if s.contains(git2::STATUS_INDEX_MODIFIED) => 'M',
        s if s.contains(git2::STATUS_INDEX_DELETED) => 'D',
        s if s.contains(git2::STATUS_INDEX_RENAMED) => 'R',
        s if s.contains(git2::STATUS_INDEX_TYPECHANGE) => 'T',
        _ => ' ',
    };
    let mut wstatus = match status {
        s if s.contains(git2::STATUS_WT_NEW) => {
            if istatus == ' ' { istatus = '?'; } '?'
        }
        s if s.contains(git2::STATUS_WT_MODIFIED) => 'M',
        s if s.contains(git2::STATUS_WT_DELETED) => 'D',
        s if s.contains(git2::STATUS_WT_RENAMED) => 'R',
        s if s.contains(git2::STATUS_WT_TYPECHANGE) => 'T',
        _ => ' ',
    };
    if status.contains(git2::STATUS_IGNORED) {
        istatus = '!';
        wstatus = '!';
    }
    // TODO: handle submodule statuses?
    format!("{}{} {}", istatus, wstatus, path)
}

fn get_status_lines(repo: Arc<Repo>) -> Vec<String> {
    let git2_repo = match repo.as_git2_repo() {
        None => {
            writeln!(&mut stderr(),
                "Could not open {} as a git repo. Perhaps you should run \
                `git global scan` again.", repo
            ).expect("failed to write to STDERR");
            return vec![];
        }
        Some(repo) => repo,
    };
    let mut opts = git2::StatusOptions::new();
    opts.show(git2::StatusShow::IndexAndWorkdir)
        .include_ignored(false);
    let statuses = git2_repo.statuses(Some(&mut opts))
        .expect(&format!("Could not get statuses for {}.", repo));
    statuses.iter().map(|entry| {
        let path = entry.path().unwrap();
        let status = entry.status();
        let status_for_path = get_short_format_status(path, status);
        // result.add_repo_message(repo, format!("{}", status_for_path));
        format!("{}", status_for_path)
    }).collect()
}

pub fn get_results() -> Result<GitGlobalResult> {
    let repos = get_repos();
    let n_repos = repos.len();
    let mut result = GitGlobalResult::new(&repos);
    result.pad_repo_output();
    // TOOD: limit number of threads, perhaps with mpsc::sync_channel(n)?
    let (tx, rx) = mpsc::channel();
    for repo in repos {
        let tx = tx.clone();
        let repo = Arc::new(repo);
        thread::spawn(move || {
            let path = repo.path();
            let lines = get_status_lines(repo);
            tx.send((path, lines)).unwrap();
        });
    }
    for _ in 0..n_repos {
        let (path, lines) = rx.recv().unwrap();
        let repo = Repo::new(path.to_string());
        for line in lines {
            result.add_repo_message(&repo, line);
        }
    }
    Ok(result)
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::HashMap;
use std::ops::Deref;
use std::rc::Rc;

use wayland_server::protocol::wl_touch::WlTouch;
use wayland_server::{Filter, Main};

use crate::backend::input::TouchSlot;
use crate::utils::{Logical, Point};
use crate::wayland::seat::wl_surface::WlSurface;

/// An handle to a touch handler.
///
/// It can be cloned and all clones manipulate the same internal state.
///
/// This handle gives you access to an interface to send touch events to your
/// clients.
#[derive(Debug, Clone)]
pub struct TouchHandle {
    inner: Rc<RefCell<TouchInternal>>,
}

impl TouchHandle {
    pub(crate) fn new() -> Self {
        Self {
            inner: Default::default(),
        }
    }

    /// Register a new touch handle to this handler
    ///
    /// This should be done first, before anything else is done with this touch handle.
    pub(crate) fn new_touch(&self, touch: WlTouch) {
        self.inner.borrow_mut().known_handles.push(touch);
    }

    /// Notify clients about new touch points.
    pub fn down(
        &mut self,
        serial: u32,
        time: u32,
        surface: &WlSurface,
        surface_offset: Point<i32, Logical>,
        slot: TouchSlot,
        location: Point<f64, Logical>,
    ) {
        self.inner
            .borrow_mut()
            .down(serial, time, surface, surface_offset, slot, location);
    }

    /// Notify clients about touch point removal.
    pub fn up(&self, serial: u32, time: u32, slot: TouchSlot) {
        self.inner.borrow_mut().up(serial, time, slot);
    }

    /// Notify clients about touch motion.
    pub fn motion(&self, time: u32, slot: TouchSlot, location: Point<f64, Logical>) {
        self.inner.borrow_mut().motion(time, slot, location);
    }

    /// Notify clients about touch shape changes.
    pub fn shape(&self, slot: TouchSlot, major: f64, minor: f64) {
        self.inner.borrow_mut().shape(slot, major, minor);
    }

    /// Notify clients about touch shape orientation.
    pub fn orientation(&self, slot: TouchSlot, orientation: f64) {
        self.inner.borrow_mut().orientation(slot, orientation);
    }

    /// Notify clients about touch cancellation.
    ///
    /// This should be sent by the compositor when the currently active touch
    /// slot was recognized as a gesture.
    pub fn cancel(&self) {
        self.inner.borrow_mut().cancel();
    }
}

/// Touch-slot focused Wayland client state.
#[derive(Default, Debug)]
struct TouchFocus {
    surface_offset: Point<f64, Logical>,
    handles: Vec<WlTouch>,
}

#[derive(Default, Debug)]
struct TouchInternal {
    known_handles: Vec<WlTouch>,
    focus: HashMap<TouchSlot, TouchFocus>,
}

impl TouchInternal {
    fn down(
        &mut self,
        serial: u32,
        time: u32,
        surface: &WlSurface,
        surface_offset: Point<i32, Logical>,
        slot: TouchSlot,
        location: Point<f64, Logical>,
    ) {
        // Update focused client state.
        let focus = self.focus.entry(slot).or_default();
        focus.surface_offset = surface_offset.to_f64();
        focus.handles.clear();

        // Select all WlTouch instances associated to the active WlSurface.
        for handle in &self.known_handles {
            if handle.as_ref().same_client_as(surface.as_ref()) {
                focus.handles.push(handle.clone());
            }
        }

        let (x, y) = (location - focus.surface_offset).into();
        self.with_focused_handles(slot, |handle| {
            handle.down(serial, time, surface, slot.into(), x, y)
        });
    }

    fn up(&self, serial: u32, time: u32, slot: TouchSlot) {
        self.with_focused_handles(slot, |handle| handle.up(serial, time, slot.into()));
    }

    fn motion(&self, time: u32, slot: TouchSlot, location: Point<f64, Logical>) {
        let focus = match self.focus.get(&slot) {
            Some(slot) => slot,
            None => return,
        };

        let (x, y) = (location - focus.surface_offset).into();
        self.with_focused_handles(slot, |handle| handle.motion(time, slot.into(), x, y));
    }

    fn shape(&self, slot: TouchSlot, major: f64, minor: f64) {
        self.with_focused_handles(slot, |handle| handle.shape(slot.into(), major, minor));
    }

    fn orientation(&self, slot: TouchSlot, orientation: f64) {
        self.with_focused_handles(slot, |handle| handle.orientation(slot.into(), orientation));
    }

    // TODO: In theory doesn't need to be sent for WlTouch that isn't in the focus hashmap?
    fn cancel(&self) {
        for handle in &self.known_handles {
            handle.cancel();
        }
    }

    // TODO: Document this also sends frame every time.
    #[inline]
    fn with_focused_handles<F>(&self, slot: TouchSlot, mut f: F)
    where
        F: FnMut(&WlTouch),
    {
        if let Some(focus) = self.focus.get(&slot) {
            for handle in &focus.handles {
                f(handle);
                handle.frame();
            }
        }
    }
}

pub(crate) fn implement_touch(touch: Main<WlTouch>, handle: Option<&TouchHandle>) -> WlTouch {
    // The sole `Release` request is already handled by our destructor.
    touch.quick_assign(|_touch, _request, _data| {});

    // Remove from touch handles on destroy.
    if let Some(handle) = handle {
        let inner = handle.inner.clone();
        touch.assign_destructor(Filter::new(move |touch: WlTouch, _, _| {
            inner
                .borrow_mut()
                .known_handles
                .retain(|t| !t.as_ref().equals(touch.as_ref()))
        }));
    }

    touch.deref().clone()
}
<commit_msg>Check version for touch shape and orientation<commit_after>use std::cell::RefCell;
use std::collections::HashMap;
use std::ops::Deref;
use std::rc::Rc;

use wayland_server::protocol::wl_touch::WlTouch;
use wayland_server::{Filter, Main};

use crate::backend::input::TouchSlot;
use crate::utils::{Logical, Point};
use crate::wayland::seat::wl_surface::WlSurface;

/// An handle to a touch handler.
///
/// It can be cloned and all clones manipulate the same internal state.
///
/// This handle gives you access to an interface to send touch events to your
/// clients.
#[derive(Debug, Clone)]
pub struct TouchHandle {
    inner: Rc<RefCell<TouchInternal>>,
}

impl TouchHandle {
    pub(crate) fn new() -> Self {
        Self {
            inner: Default::default(),
        }
    }

    /// Register a new touch handle to this handler
    ///
    /// This should be done first, before anything else is done with this touch handle.
    pub(crate) fn new_touch(&self, touch: WlTouch) {
        self.inner.borrow_mut().known_handles.push(touch);
    }

    /// Notify clients about new touch points.
    pub fn down(
        &mut self,
        serial: u32,
        time: u32,
        surface: &WlSurface,
        surface_offset: Point<i32, Logical>,
        slot: TouchSlot,
        location: Point<f64, Logical>,
    ) {
        self.inner
            .borrow_mut()
            .down(serial, time, surface, surface_offset, slot, location);
    }

    /// Notify clients about touch point removal.
    pub fn up(&self, serial: u32, time: u32, slot: TouchSlot) {
        self.inner.borrow_mut().up(serial, time, slot);
    }

    /// Notify clients about touch motion.
    pub fn motion(&self, time: u32, slot: TouchSlot, location: Point<f64, Logical>) {
        self.inner.borrow_mut().motion(time, slot, location);
    }

    /// Notify clients about touch shape changes.
    pub fn shape(&self, slot: TouchSlot, major: f64, minor: f64) {
        self.inner.borrow_mut().shape(slot, major, minor);
    }

    /// Notify clients about touch shape orientation.
    pub fn orientation(&self, slot: TouchSlot, orientation: f64) {
        self.inner.borrow_mut().orientation(slot, orientation);
    }

    /// Notify clients about touch cancellation.
    ///
    /// This should be sent by the compositor when the currently active touch
    /// slot was recognized as a gesture.
    pub fn cancel(&self) {
        self.inner.borrow_mut().cancel();
    }
}

/// Touch-slot focused Wayland client state.
#[derive(Default, Debug)]
struct TouchFocus {
    surface_offset: Point<f64, Logical>,
    handles: Vec<WlTouch>,
}

#[derive(Default, Debug)]
struct TouchInternal {
    known_handles: Vec<WlTouch>,
    focus: HashMap<TouchSlot, TouchFocus>,
}

impl TouchInternal {
    fn down(
        &mut self,
        serial: u32,
        time: u32,
        surface: &WlSurface,
        surface_offset: Point<i32, Logical>,
        slot: TouchSlot,
        location: Point<f64, Logical>,
    ) {
        // Update focused client state.
        let focus = self.focus.entry(slot).or_default();
        focus.surface_offset = surface_offset.to_f64();
        focus.handles.clear();

        // Select all WlTouch instances associated to the active WlSurface.
        for handle in &self.known_handles {
            if handle.as_ref().same_client_as(surface.as_ref()) {
                focus.handles.push(handle.clone());
            }
        }

        let (x, y) = (location - focus.surface_offset).into();
        self.with_focused_handles(slot, |handle| {
            handle.down(serial, time, surface, slot.into(), x, y)
        });
    }

    fn up(&self, serial: u32, time: u32, slot: TouchSlot) {
        self.with_focused_handles(slot, |handle| handle.up(serial, time, slot.into()));
    }

    fn motion(&self, time: u32, slot: TouchSlot, location: Point<f64, Logical>) {
        let focus = match self.focus.get(&slot) {
            Some(slot) => slot,
            None => return,
        };

        let (x, y) = (location - focus.surface_offset).into();
        self.with_focused_handles(slot, |handle| handle.motion(time, slot.into(), x, y));
    }

    fn shape(&self, slot: TouchSlot, major: f64, minor: f64) {
        self.with_focused_handles(slot, |handle| {
            if handle.as_ref().version() >= 6 {
                handle.shape(slot.into(), major, minor);
            }
        });
    }

    fn orientation(&self, slot: TouchSlot, orientation: f64) {
        self.with_focused_handles(slot, |handle| {
            if handle.as_ref().version() >= 6 {
                handle.orientation(slot.into(), orientation);
            }
        });
    }

    // TODO: In theory doesn't need to be sent for WlTouch that isn't in the focus hashmap?
    fn cancel(&self) {
        for handle in &self.known_handles {
            handle.cancel();
        }
    }

    // TODO: Document this also sends frame every time.
    #[inline]
    fn with_focused_handles<F>(&self, slot: TouchSlot, mut f: F)
    where
        F: FnMut(&WlTouch),
    {
        if let Some(focus) = self.focus.get(&slot) {
            for handle in &focus.handles {
                f(handle);
                handle.frame();
            }
        }
    }
}

pub(crate) fn implement_touch(touch: Main<WlTouch>, handle: Option<&TouchHandle>) -> WlTouch {
    // The sole `Release` request is already handled by our destructor.
    touch.quick_assign(|_touch, _request, _data| {});

    // Remove from touch handles on destroy.
    if let Some(handle) = handle {
        let inner = handle.inner.clone();
        touch.assign_destructor(Filter::new(move |touch: WlTouch, _, _| {
            inner
                .borrow_mut()
                .known_handles
                .retain(|t| !t.as_ref().equals(touch.as_ref()))
        }));
    }

    touch.deref().clone()
}
<|endoftext|>


<commit_before>//! Slither Link solver logic.

#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
// #![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate union_find;
extern crate srither_core;

use std::{fmt, mem};
use std::error::Error as ErrorTrait;

use srither_core::puzzle::Puzzle;
use srither_core::geom::CellId;

use solver::Solver;
use theorem_define::THEOREM_DEFINE;

mod model {
    pub mod connect_map;
    pub mod side_map;
    pub mod theorem;
}
mod step {
    pub mod apply_theorem;
    pub mod connect_analysis;
}
mod theorem_define;
mod solver;

#[derive(Copy, Clone, Debug)]
pub struct Error {
    kind: ErrorKind,
}

#[derive(Copy, Clone, Debug)]
enum ErrorKind {
    InvalidBoard,
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        match self.kind {
            ErrorKind::InvalidBoard => "invalid board data",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl Error {
    fn invalid_board() -> Error {
        Error { kind: ErrorKind::InvalidBoard }
    }
}

pub type SolverResult<T> = Result<T, Error>;

enum FillResult<'a> {
    Completed(Solver<'a>),
    Partial(Solver<'a>, Vec<CellId>),
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum State<T> {
    Fixed(T),
    Unknown,
    Conflict,
}

impl<T> Into<SolverResult<Option<T>>> for State<T> {
    fn into(self) -> SolverResult<Option<T>> {
        match self {
            State::Fixed(st) => Ok(Some(st)),
            State::Unknown => Ok(None),
            State::Conflict => Err(Error::invalid_board()),
        }
    }
}

fn fill_absolutely_fixed(solver: &mut Solver) -> SolverResult<()> {
    while !solver.all_filled() {
        let rev = solver.revision();

        try!(solver.apply_all_theorem());
        if solver.revision() != rev {
            continue;
        }

        try!(solver.connect_analysis());
        if solver.revision() != rev {
            continue;
        }

        break;
    }

    Ok(())
}

fn fill_by_shallow_backtracking(solver: &mut Solver, pts: &[CellId]) -> SolverResult<bool> {
    let rev = solver.revision();
    let mut solver_in = solver.clone();
    let mut solver_out = solver.clone();

    for &p in pts {
        match solver.get_side(p) {
            State::Fixed(_) => {
                continue;
            }
            State::Unknown => {}
            State::Conflict => {
                return Err(Error::invalid_board());
            }
        }

        solver_in.clone_from(&solver);
        solver_in.set_inside(p);

        if fill_absolutely_fixed(&mut solver_in).is_err() {
            solver.set_outside(p);
            try!(fill_absolutely_fixed(solver));
            continue;
        }

        solver_out.clone_from(&solver);
        solver_out.set_outside(p);

        if fill_absolutely_fixed(&mut solver_out).is_err() {
            mem::swap(solver, &mut solver_in);
            continue;
        }

        solver.mark_common(&mut solver_in, &mut solver_out);
    }

    Ok(solver.revision() != rev)
}

fn fill(mut solver: Solver) -> SolverResult<FillResult> {
    try!(fill_absolutely_fixed(&mut solver));

    if solver.all_filled() {
        return Ok(FillResult::Completed(solver));
    }

    let mut pts = solver.get_unknown_points();
    while try!(fill_by_shallow_backtracking(&mut solver, &pts)) {
        if solver.all_filled() {
            return Ok(FillResult::Completed(solver));
        }
        pts = solver.get_unknown_points();
    }

    Ok(FillResult::Partial(solver, pts))
}

#[derive(Clone, Debug)]
pub struct Solutions<'a> {
    queue: Vec<Solver<'a>>,
}

impl<'a> Solutions<'a> {
    pub fn new(puzzle: &'a Puzzle) -> SolverResult<Solutions<'a>> {
        let theorem = THEOREM_DEFINE.iter().map(|theo| theo.parse().unwrap());
        Ok(Solutions { queue: vec![try!(Solver::new(puzzle, theorem))] })
    }
}

impl<'a> Iterator for Solutions<'a> {
    type Item = Puzzle;

    fn next(&mut self) -> Option<Puzzle> {
        while let Some(solver) = self.queue.pop() {
            let (solver, pts) = match fill(solver) {
                Ok(FillResult::Completed(mut solver)) => {
                    if solver.validate_result().is_err() {
                        continue;
                    }
                    match solver.into() {
                        Ok(result) => return Some(result),
                        Err(_) => continue,
                    }
                }
                Ok(FillResult::Partial(solver, pts)) => (solver, pts),
                Err(_) => continue,
            };
            let p = *pts.last().unwrap();
            let mut solver_in = solver.clone();
            let mut solver_out = solver;
            solver_in.set_inside(p);
            solver_out.set_outside(p);
            self.queue.push(solver_in);
            self.queue.push(solver_out);
        }

        None
    }
}

pub fn solve(puzzle: &Puzzle) -> SolverResult<Puzzle> {
    let mut it = try!(Solutions::new(puzzle));
    if let Some(solution) = it.next() {
        return Ok(solution);
    }

    Err(Error::invalid_board())
}
<commit_msg>srither-solver: Add documentation.<commit_after>//! Slither Link solver logic.

#![warn(bad_style)]
#![warn(missing_copy_implementations)]
#![warn(missing_debug_implementations)]
#![warn(missing_docs)]
#![warn(trivial_casts)]
#![warn(trivial_numeric_casts)]
#![warn(unused)]
#![warn(unused_extern_crates)]
#![warn(unused_import_braces)]
#![warn(unused_qualifications)]
#![warn(unused_results)]

extern crate union_find;
extern crate srither_core;

use std::{fmt, mem};
use std::error::Error as ErrorTrait;

use srither_core::puzzle::Puzzle;
use srither_core::geom::CellId;

use solver::Solver;
use theorem_define::THEOREM_DEFINE;

mod model {
    pub mod connect_map;
    pub mod side_map;
    pub mod theorem;
}
mod step {
    pub mod apply_theorem;
    pub mod connect_analysis;
}
mod theorem_define;
mod solver;

/// An error type which is returned from solving a puzzle.
#[derive(Copy, Clone, Debug)]
pub struct Error {
    kind: ErrorKind,
}

#[derive(Copy, Clone, Debug)]
enum ErrorKind {
    InvalidBoard,
}

impl ErrorTrait for Error {
    fn description(&self) -> &str {
        match self.kind {
            ErrorKind::InvalidBoard => "invalid board data",
        }
    }
}

impl fmt::Display for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.description().fmt(f)
    }
}

impl Error {
    fn invalid_board() -> Error {
        Error { kind: ErrorKind::InvalidBoard }
    }
}

/// Solving puzzles result.
pub type SolverResult<T> = Result<T, Error>;

enum FillResult<'a> {
    Completed(Solver<'a>),
    Partial(Solver<'a>, Vec<CellId>),
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
enum State<T> {
    Fixed(T),
    Unknown,
    Conflict,
}

impl<T> Into<SolverResult<Option<T>>> for State<T> {
    fn into(self) -> SolverResult<Option<T>> {
        match self {
            State::Fixed(st) => Ok(Some(st)),
            State::Unknown => Ok(None),
            State::Conflict => Err(Error::invalid_board()),
        }
    }
}

fn fill_absolutely_fixed(solver: &mut Solver) -> SolverResult<()> {
    while !solver.all_filled() {
        let rev = solver.revision();

        try!(solver.apply_all_theorem());
        if solver.revision() != rev {
            continue;
        }

        try!(solver.connect_analysis());
        if solver.revision() != rev {
            continue;
        }

        break;
    }

    Ok(())
}

fn fill_by_shallow_backtracking(solver: &mut Solver, pts: &[CellId]) -> SolverResult<bool> {
    let rev = solver.revision();
    let mut solver_in = solver.clone();
    let mut solver_out = solver.clone();

    for &p in pts {
        match solver.get_side(p) {
            State::Fixed(_) => {
                continue;
            }
            State::Unknown => {}
            State::Conflict => {
                return Err(Error::invalid_board());
            }
        }

        solver_in.clone_from(&solver);
        solver_in.set_inside(p);

        if fill_absolutely_fixed(&mut solver_in).is_err() {
            solver.set_outside(p);
            try!(fill_absolutely_fixed(solver));
            continue;
        }

        solver_out.clone_from(&solver);
        solver_out.set_outside(p);

        if fill_absolutely_fixed(&mut solver_out).is_err() {
            mem::swap(solver, &mut solver_in);
            continue;
        }

        solver.mark_common(&mut solver_in, &mut solver_out);
    }

    Ok(solver.revision() != rev)
}

fn fill(mut solver: Solver) -> SolverResult<FillResult> {
    try!(fill_absolutely_fixed(&mut solver));

    if solver.all_filled() {
        return Ok(FillResult::Completed(solver));
    }

    let mut pts = solver.get_unknown_points();
    while try!(fill_by_shallow_backtracking(&mut solver, &pts)) {
        if solver.all_filled() {
            return Ok(FillResult::Completed(solver));
        }
        pts = solver.get_unknown_points();
    }

    Ok(FillResult::Partial(solver, pts))
}

/// An iterator iterates all solutions of the puzzle.
#[derive(Clone, Debug)]
pub struct Solutions<'a> {
    queue: Vec<Solver<'a>>,
}

impl<'a> Solutions<'a> {
    /// Creates an solutions iterator of the puzzle.
    pub fn new(puzzle: &'a Puzzle) -> SolverResult<Solutions<'a>> {
        let theorem = THEOREM_DEFINE.iter().map(|theo| theo.parse().unwrap());
        Ok(Solutions { queue: vec![try!(Solver::new(puzzle, theorem))] })
    }
}

impl<'a> Iterator for Solutions<'a> {
    type Item = Puzzle;

    fn next(&mut self) -> Option<Puzzle> {
        while let Some(solver) = self.queue.pop() {
            let (solver, pts) = match fill(solver) {
                Ok(FillResult::Completed(mut solver)) => {
                    if solver.validate_result().is_err() {
                        continue;
                    }
                    match solver.into() {
                        Ok(result) => return Some(result),
                        Err(_) => continue,
                    }
                }
                Ok(FillResult::Partial(solver, pts)) => (solver, pts),
                Err(_) => continue,
            };
            let p = *pts.last().unwrap();
            let mut solver_in = solver.clone();
            let mut solver_out = solver;
            solver_in.set_inside(p);
            solver_out.set_outside(p);
            self.queue.push(solver_in);
            self.queue.push(solver_out);
        }

        None
    }
}

/// Returns the first solution of the puzzle.
pub fn solve(puzzle: &Puzzle) -> SolverResult<Puzzle> {
    let mut it = try!(Solutions::new(puzzle));
    if let Some(solution) = it.next() {
        return Ok(solution);
    }

    Err(Error::invalid_board())
}
<|endoftext|>