<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 azure::{AzScaledFontRef, AzFloat};
use azure::{struct__AzNativeFont};

use azure_hl::{BackendType,SkiaBackend};
use azure::{AzCreateScaledFontForNativeFont, AzReleaseScaledFont};

use libc::c_void;
use std::mem;
use std::ptr;

#[cfg(target_os="macos")]
use scaled_font::macos::*;

#[cfg(target_os="linux")]
use scaled_font::linux::*;

#[cfg(target_os="android")]
use scaled_font::android::*;

#[cfg(target_os="macos")]
pub mod macos {
    pub use scaled_font::macos::core_text::font::CTFontRef;
    pub use scaled_font::macos::core_graphics::font::{CGFont, CGFontRef};
}

#[cfg(target_os="linux")]
pub mod linux {
    pub use scaled_font::linux::freetype::freetype::{FT_Face, FT_LOAD_DEFAULT};
}

#[cfg(target_os="android")]
pub mod android {
    pub use scaled_font::android::freetype::freetype::{FT_Face, FT_LOAD_DEFAULT};
}

pub type SkTypeface = *mut c_void;

#[cfg(target_os="linux")]
#[cfg(target_os="android")]
pub enum FontInfo<'a> {
    NativeFont(FT_Face),
    FontData(&'a Vec<u8>),
}

pub struct ScaledFont {
    azure_scaled_font: AzScaledFontRef,
}

impl Drop for ScaledFont {
    fn drop(&mut self) {
        unsafe {
            AzReleaseScaledFont(self.azure_scaled_font);
        }
    }
}

impl ScaledFont {
    pub fn get_ref(&self) -> AzScaledFontRef {
        self.azure_scaled_font
    }

    #[cfg(target_os="linux")]
    #[cfg(target_os="android")]
    pub fn new(backend: BackendType, font_info: FontInfo, size: AzFloat)
        -> ScaledFont {
        use azure::AZ_NATIVE_FONT_SKIA_FONT_FACE;
        use azure::{AzCreateFontOptionsForData, AzCreateFontOptionsForName, AzDestroyFontOptions};

        let mut azure_native_font = struct__AzNativeFont {
            mType: 0,
            mFont: ptr::mut_null()
        };

        match backend {
            SkiaBackend => {
                unsafe {
                    let options = match font_info {
                        NativeFont(native_font) => {
                            // NOTE: azure style flags and freetype style flags are the same in the lowest 2 bits
                            let style = ((*native_font).style_flags & 3) as u32;
                            AzCreateFontOptionsForName(&*(*native_font).family_name, style)
                        },
                        FontData(bytes) => {
                            AzCreateFontOptionsForData(bytes.as_ptr(), bytes.len() as u32)
                        },
                    };
                    azure_native_font.mType = AZ_NATIVE_FONT_SKIA_FONT_FACE;
                    azure_native_font.mFont = mem::transmute(options);
                    let azure_native_font_ptr = &mut azure_native_font;
                    let azure_scaled_font = AzCreateScaledFontForNativeFont(azure_native_font_ptr, size);
                    AzDestroyFontOptions(options);
                    ScaledFont { azure_scaled_font: azure_scaled_font }
                }
            }
            _ => { fail!("don't know how to make a scaled font for this backend"); }
        }
    }

    /// Mac-specific function to create a font for the given backend.
    #[cfg(target_os="macos")]
    pub fn new(backend: BackendType, native_font: &CGFont, size: AzFloat) -> ScaledFont {
        use azure::AZ_NATIVE_FONT_MAC_FONT_FACE;
        use azure_hl::{CoreGraphicsBackend,CoreGraphicsAcceleratedBackend};
        use scaled_font::macos::core_foundation::base::TCFType;

        let mut azure_native_font = struct__AzNativeFont {
            mType: 0,
            mFont: ptr::mut_null()
        };

        match backend {
            CoreGraphicsBackend | CoreGraphicsAcceleratedBackend | SkiaBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_MAC_FONT_FACE;
                unsafe {
                    azure_native_font.mFont = mem::transmute(native_font.as_concrete_TypeRef());
                }
            }
            _ => {
                fail!("don't know how to make a scaled font for this backend");
            }
        }

        unsafe {
            let azure_scaled_font = AzCreateScaledFontForNativeFont(&mut azure_native_font, size);
            ScaledFont {
                azure_scaled_font: azure_scaled_font
            }
        }
    }
}

// FIXME: Move this stuff to a rust-skia?
// FIXME: Demangle the names!!!
#[cfg(target_os="macos")]
#[link(name = "skia")]
extern {
    pub fn _Z26SkCreateTypefaceFromCTFontPK8__CTFont(font: CTFontRef) -> *mut SkTypeface;
}

<commit_msg>Fix crate paths which changed<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 azure::{AzScaledFontRef, AzFloat};
use azure::{struct__AzNativeFont};

use azure_hl::{BackendType,SkiaBackend};
use azure::{AzCreateScaledFontForNativeFont, AzReleaseScaledFont};

use libc::c_void;
use std::mem;
use std::ptr;

#[cfg(target_os="macos")]
use scaled_font::macos::*;

#[cfg(target_os="linux")]
use scaled_font::linux::*;

#[cfg(target_os="android")]
use scaled_font::android::*;

#[cfg(target_os="macos")]
pub mod macos {
    pub use core_text::font::CTFontRef;
    pub use core_graphics::font::{CGFont, CGFontRef};
}

#[cfg(target_os="linux")]
pub mod linux {
    pub use freetype::freetype::{FT_Face, FT_LOAD_DEFAULT};
}

#[cfg(target_os="android")]
pub mod android {
    pub use freetype::freetype::{FT_Face, FT_LOAD_DEFAULT};
}

pub type SkTypeface = *mut c_void;

#[cfg(target_os="linux")]
#[cfg(target_os="android")]
pub enum FontInfo<'a> {
    NativeFont(FT_Face),
    FontData(&'a Vec<u8>),
}

pub struct ScaledFont {
    azure_scaled_font: AzScaledFontRef,
}

impl Drop for ScaledFont {
    fn drop(&mut self) {
        unsafe {
            AzReleaseScaledFont(self.azure_scaled_font);
        }
    }
}

impl ScaledFont {
    pub fn get_ref(&self) -> AzScaledFontRef {
        self.azure_scaled_font
    }

    #[cfg(target_os="linux")]
    #[cfg(target_os="android")]
    pub fn new(backend: BackendType, font_info: FontInfo, size: AzFloat)
        -> ScaledFont {
        use azure::AZ_NATIVE_FONT_SKIA_FONT_FACE;
        use azure::{AzCreateFontOptionsForData, AzCreateFontOptionsForName, AzDestroyFontOptions};

        let mut azure_native_font = struct__AzNativeFont {
            mType: 0,
            mFont: ptr::mut_null()
        };

        match backend {
            SkiaBackend => {
                unsafe {
                    let options = match font_info {
                        NativeFont(native_font) => {
                            // NOTE: azure style flags and freetype style flags are the same in the lowest 2 bits
                            let style = ((*native_font).style_flags & 3) as u32;
                            AzCreateFontOptionsForName(&*(*native_font).family_name, style)
                        },
                        FontData(bytes) => {
                            AzCreateFontOptionsForData(bytes.as_ptr(), bytes.len() as u32)
                        },
                    };
                    azure_native_font.mType = AZ_NATIVE_FONT_SKIA_FONT_FACE;
                    azure_native_font.mFont = mem::transmute(options);
                    let azure_native_font_ptr = &mut azure_native_font;
                    let azure_scaled_font = AzCreateScaledFontForNativeFont(azure_native_font_ptr, size);
                    AzDestroyFontOptions(options);
                    ScaledFont { azure_scaled_font: azure_scaled_font }
                }
            }
            _ => { fail!("don't know how to make a scaled font for this backend"); }
        }
    }

    /// Mac-specific function to create a font for the given backend.
    #[cfg(target_os="macos")]
    pub fn new(backend: BackendType, native_font: &CGFont, size: AzFloat) -> ScaledFont {
        use azure::AZ_NATIVE_FONT_MAC_FONT_FACE;
        use azure_hl::{CoreGraphicsBackend,CoreGraphicsAcceleratedBackend};
        use scaled_font::macos::core_foundation::base::TCFType;

        let mut azure_native_font = struct__AzNativeFont {
            mType: 0,
            mFont: ptr::mut_null()
        };

        match backend {
            CoreGraphicsBackend | CoreGraphicsAcceleratedBackend | SkiaBackend => {
                azure_native_font.mType = AZ_NATIVE_FONT_MAC_FONT_FACE;
                unsafe {
                    azure_native_font.mFont = mem::transmute(native_font.as_concrete_TypeRef());
                }
            }
            _ => {
                fail!("don't know how to make a scaled font for this backend");
            }
        }

        unsafe {
            let azure_scaled_font = AzCreateScaledFontForNativeFont(&mut azure_native_font, size);
            ScaledFont {
                azure_scaled_font: azure_scaled_font
            }
        }
    }
}

// FIXME: Move this stuff to a rust-skia?
// FIXME: Demangle the names!!!
#[cfg(target_os="macos")]
#[link(name = "skia")]
extern {
    pub fn _Z26SkCreateTypefaceFromCTFontPK8__CTFont(font: CTFontRef) -> *mut SkTypeface;
}

<|endoftext|>


<commit_before>#![feature(globs)]
#![crate_type = "bin"]

extern crate rgtk;
extern crate log;
extern crate collections;

use std::f64::consts::PI_2;

use rgtk::*;
use rgtk::gtk::signals::{DeleteEvent, Draw};
use rgtk::gtk::DrawingArea;

use rgtk::cairo::enums::{
    FontSlantNormal,
    FontWeightNormal
};

fn main() {
    gtk::init();

    drawable(500, 500, |cr| {
        cr.scale(500.0, 500.0);

        cr.set_source_rgb(250.0/255.0, 224.0/255.0, 55.0/255.0);
        cr.paint();

        cr.set_line_width(0.05);

        // border
        cr.set_source_rgb(0.3, 0.3, 0.3);
        cr.rectangle(0.0, 0.0, 1.0, 1.0);
        cr.stroke();

        cr.set_line_width(0.03);

        // draw circle
        cr.arc(0.5, 0.5, 0.4, 0.0, PI_2);
        cr.stroke();

        // mouth
        let mouth_top = 0.68;
        let mouth_width = 0.38;

        let mouth_dx = 0.10;
        let mouth_dy = 0.10;

        cr.move_to( 0.50 - mouth_width/2.0, mouth_top);
        cr.curve_to(0.50 - mouth_dx,        mouth_top + mouth_dy,
                     0.50 + mouth_dx,        mouth_top + mouth_dy,
                     0.50 + mouth_width/2.0, mouth_top);

        println!("Extents: {}", cr.fill_extents());

        cr.stroke();

        let eye_y = 0.38;
        let eye_dx = 0.15;
        cr.arc(0.5 - eye_dx, eye_y, 0.05, 0.0, PI_2);
        cr.fill();

        cr.arc(0.5 + eye_dx, eye_y, 0.05, 0.0, PI_2);
        cr.fill();
    });

    drawable(500, 500, |cr| {
        cr.scale(500.0, 500.0);

        cr.select_font_face("Sans",
                              cairo::enums::FontSlantNormal,
                              cairo::enums::FontWeightNormal);
        cr.set_font_size(0.35);

        cr.move_to(0.04, 0.53);
        cr.show_text("Hello");

        cr.move_to(0.27, 0.65);
        cr.text_path("void");
        cr.set_source_rgb(0.5, 0.5, 1.0);
        cr.fill_preserve();
        cr.set_source_rgb(0.0, 0.0, 0.0);
        cr.set_line_width(0.01);
        cr.stroke();

        cr.set_source_rgba(1.0, 0.2, 0.2, 0.6);
        cr.arc(0.04, 0.53, 0.02, 0.0, PI_2);
        cr.arc(0.27, 0.65, 0.02, 0.0, PI_2);
        cr.fill();
    });

    gtk::main();
}

pub fn drawable(width: i32, height: i32, draw_fn: |cairo::Context|) {
    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    let drawing_area = box DrawingArea::new().unwrap();

    Connect::connect(&*drawing_area, Draw::new(draw_fn));

    window.set_default_size(width, height);

    Connect::connect(&window, DeleteEvent::new(|_|{
        gtk::main_quit();
        true
    }));
    window.add(&*drawing_area);
    window.show_all();
}
<commit_msg>Fix cairotest build error<commit_after>#![feature(globs)]
#![crate_type = "bin"]

extern crate rgtk;
extern crate log;
extern crate collections;

use std::f64::consts::PI_2;

use rgtk::*;
use rgtk::gtk::signals::{DeleteEvent, Draw};
use rgtk::gtk::DrawingArea;

use rgtk::cairo::enums::FontSlant::FontSlantNormal;
use rgtk::cairo::enums::FontWeight::FontWeightNormal;

fn main() {
    gtk::init();

    drawable(500, 500, |cr| {
        cr.scale(500.0, 500.0);

        cr.set_source_rgb(250.0/255.0, 224.0/255.0, 55.0/255.0);
        cr.paint();

        cr.set_line_width(0.05);

        // border
        cr.set_source_rgb(0.3, 0.3, 0.3);
        cr.rectangle(0.0, 0.0, 1.0, 1.0);
        cr.stroke();

        cr.set_line_width(0.03);

        // draw circle
        cr.arc(0.5, 0.5, 0.4, 0.0, PI_2);
        cr.stroke();

        // mouth
        let mouth_top = 0.68;
        let mouth_width = 0.38;

        let mouth_dx = 0.10;
        let mouth_dy = 0.10;

        cr.move_to( 0.50 - mouth_width/2.0, mouth_top);
        cr.curve_to(0.50 - mouth_dx,        mouth_top + mouth_dy,
                     0.50 + mouth_dx,        mouth_top + mouth_dy,
                     0.50 + mouth_width/2.0, mouth_top);

        println!("Extents: {}", cr.fill_extents());

        cr.stroke();

        let eye_y = 0.38;
        let eye_dx = 0.15;
        cr.arc(0.5 - eye_dx, eye_y, 0.05, 0.0, PI_2);
        cr.fill();

        cr.arc(0.5 + eye_dx, eye_y, 0.05, 0.0, PI_2);
        cr.fill();
    });

    drawable(500, 500, |cr| {
        cr.scale(500.0, 500.0);

        cr.select_font_face("Sans", FontSlantNormal, FontWeightNormal);
        cr.set_font_size(0.35);

        cr.move_to(0.04, 0.53);
        cr.show_text("Hello");

        cr.move_to(0.27, 0.65);
        cr.text_path("void");
        cr.set_source_rgb(0.5, 0.5, 1.0);
        cr.fill_preserve();
        cr.set_source_rgb(0.0, 0.0, 0.0);
        cr.set_line_width(0.01);
        cr.stroke();

        cr.set_source_rgba(1.0, 0.2, 0.2, 0.6);
        cr.arc(0.04, 0.53, 0.02, 0.0, PI_2);
        cr.arc(0.27, 0.65, 0.02, 0.0, PI_2);
        cr.fill();
    });

    gtk::main();
}

pub fn drawable(width: i32, height: i32, draw_fn: |cairo::Context|) {
    let mut window = gtk::Window::new(gtk::WindowType::TopLevel).unwrap();
    let drawing_area = box DrawingArea::new().unwrap();

    Connect::connect(&*drawing_area, Draw::new(draw_fn));

    window.set_default_size(width, height);

    Connect::connect(&window, DeleteEvent::new(|_|{
        gtk::main_quit();
        true
    }));
    window.add(&*drawing_area);
    window.show_all();
}
<|endoftext|>


<commit_before>mod database;
mod s3;

use self::database::DatabaseBackend;
use self::s3::S3Backend;
use failure::Error;
use time::Timespec;

#[derive(Debug, PartialEq, Eq)]
pub(crate) struct Blob {
    pub(crate) path: String,
    pub(crate) mime: String,
    pub(crate) date_updated: Timespec,
    pub(crate) content: Vec<u8>,
}

pub(crate) enum Storage<'a> {
    Database(DatabaseBackend<'a>),
    S3(S3Backend<'a>),
}

impl Storage<'_> {
    pub(crate) fn get(&self, path: &str) -> Result<Blob, Error> {
        match self {
            Self::Database(db) => db.get(path),
            Self::S3(s3) => s3.get(path),
        }
    }
}
<commit_msg>Add some impls<commit_after>mod database;
mod s3;

use self::database::DatabaseBackend;
use self::s3::S3Backend;
use failure::Error;
use time::Timespec;

#[derive(Debug, PartialEq, Eq)]
pub(crate) struct Blob {
    pub(crate) path: String,
    pub(crate) mime: String,
    pub(crate) date_updated: Timespec,
    pub(crate) content: Vec<u8>,
}

pub(crate) enum Storage<'a> {
    Database(DatabaseBackend<'a>),
    S3(S3Backend<'a>),
}

impl Storage<'_> {
    pub(crate) fn get(&self, path: &str) -> Result<Blob, Error> {
        match self {
            Self::Database(db) => db.get(path),
            Self::S3(s3) => s3.get(path),
        }
    }
}

impl<'a> From<DatabaseBackend<'a>> for Storage<'a> {
    fn from(db: DatabaseBackend<'a>) -> Self {
        Self::Database(db)
    }
}

impl<'a> From<S3Backend<'a>> for Storage<'a> {
    fn from(db: S3Backend<'a>) -> Self {
        Self::S3(db)
    }
}
<|endoftext|>


<commit_before>extern crate config;

#[test]
fn conf_from_file() {
    assert!(true);
}
<commit_msg>Added a descriptive unit test as an example use case for the library.<commit_after>extern crate config;

use std::path::Path;

use config::reader;
use config::types::Value;
use config::types::ScalarValue;

#[test]
fn conf_from_file() {
    let my_conf = reader::from_file(Path::new("tests/sample.conf"));
    assert!(my_conf.is_ok());

    // Configuration was successfully parsed and is now loaded
    let configuration = my_conf.unwrap();

    // Lookup in this case will return an Option<&String>
    let my_app_title = configuration.lookup_str("application.window.title");
    assert!(my_app_title.is_some());
    assert_eq!(&my_app_title.unwrap()[..], "My Application");

    // Accessing out-of-bound positions in arrays or lists will result in a None being returned
    let out_of_bounds = configuration.lookup_str("list.[2].[0].[0]");
    assert!(out_of_bounds.is_none());

    // Lists are heterogeneous. Let's browse a list
    let list_example1 = configuration.lookup_boolean("list.[4].a.[2]");
    assert!(list_example1.is_some());
    assert_eq!(list_example1.unwrap(), true);

    // What if we don't know what type is a specific list element?
    // We can use a generic lookup and then match it
    let list_element_unknown_type = configuration.lookup("books.[0]");
    assert!(list_element_unknown_type.is_some());
    let unknown_type = list_element_unknown_type.unwrap();
    let matches_expected =
        match unknown_type {
            &Value::Svalue(ScalarValue::Integer32(_)) => { /* It's an integer */ false },
            &Value::Svalue(ScalarValue::Floating32(_)) => { /* It's a floating32 */ false },
            /* ... */
            &Value::Svalue(ScalarValue::Str(ref s)) => {
                /* It's a string */
                &s[..] == "inventory" },
            _ => false
        };
    assert!(matches_expected);

    // Find and inspect the list of known states
    if let Some(&Value::Array(ref array)) = configuration.lookup("application.group1.states") {
        // How many states do we know?
        let states_count = array.len();
        assert_eq!(states_count, 5);

        // California here we go!

        // With another lookup...
        let california = configuration.lookup_str("application.group1.states.[1]");
        assert!(california.is_some());
        assert_eq!(&california.unwrap()[..], "CA");

        // Or accessing it directly
        let ca = &array[1];
        assert_eq!(ca, &Value::Svalue(ScalarValue::Str("CA".to_string())));
    } else {
        assert!(false);
    }
}
<|endoftext|>


<commit_before>use service::Service;
use futures::{BoxFuture, Async, Future};
use super::{TailRequest, TailResponse};
use store::Store;

use Error;

/// The main interface to the outside world.
#[derive(Clone,Debug)]
pub struct TailService<S> {
    store: S,
}

impl<S: Store> TailService<S> {
    pub fn new(store: S) -> Self {
        TailService { store: store }
    }
}

impl<S: Store + Send> Service for TailService<S>
    where S::FetchFut: Send + 'static
{
    // The type of the input requests we get.
    type Request = TailRequest;
    type Response = TailResponse;
    type Error = Error;
    type Future = BoxFuture<Self::Response, Self::Error>;

    fn poll_ready(&self) -> Async<()> {
        Async::Ready(())
    }
    fn call(&self, req: Self::Request) -> Self::Future {
        debug!("TailService#call: {:?}", req);
        match req {
            TailRequest::FetchNextAfter(pos) => {
                self.store
                    .fetch_next(pos)
                    .map(|(pos, val)| TailResponse::NextItem(pos, val))
                    .map_err(|e| e.into())
                    .then(|r| {
                        debug!("Response: {:?}", r);
                        r
                    })
                    .boxed()
            }
        }
        // futures::finished(TailResponse::NextItem(LogPos::zero(), vec![]))
    }
}

#[cfg(test)]
mod test {
    use futures::{Future, Async};
    use service::Service;
    use replica::LogPos;
    use store::{Store, RamStore};
    use tail::messages::*;
    use super::*;

    #[test]
    fn should_defer_read_from_empty_log() {
        let store = RamStore::new();
        let tail = TailService::new(store.clone());

        let mut resp = tail.call(TailRequest::FetchNextAfter(LogPos::zero()));

        assert_eq!(resp.poll().expect("fut"), Async::NotReady)
    }

    #[test]
    fn shuold_yield_first_item_after_write() {
        let store = RamStore::new();
        let tail = TailService::new(store.clone());

        let mut resp = tail.call(TailRequest::FetchNextAfter(LogPos::zero()));
        let next = LogPos::zero().next();
        store.append_entry(LogPos::zero(), next, b"foo".to_vec()).wait().expect("append_entry 1");

        assert_eq!(resp.poll().expect("fut"),
                   Async::Ready(TailResponse::NextItem(next, b"foo".to_vec())));
    }

}
<commit_msg>Use task in tail::server tests too, as they depend on RamStore.<commit_after>use service::Service;
use futures::{BoxFuture, Async, Future};
use super::{TailRequest, TailResponse};
use store::Store;

use Error;

/// The main interface to the outside world.
#[derive(Clone,Debug)]
pub struct TailService<S> {
    store: S,
}

impl<S: Store> TailService<S> {
    pub fn new(store: S) -> Self {
        TailService { store: store }
    }
}

impl<S: Store + Send> Service for TailService<S>
    where S::FetchFut: Send + 'static
{
    // The type of the input requests we get.
    type Request = TailRequest;
    type Response = TailResponse;
    type Error = Error;
    type Future = BoxFuture<Self::Response, Self::Error>;

    fn poll_ready(&self) -> Async<()> {
        Async::Ready(())
    }
    fn call(&self, req: Self::Request) -> Self::Future {
        debug!("TailService#call: {:?}", req);
        match req {
            TailRequest::FetchNextAfter(pos) => {
                self.store
                    .fetch_next(pos)
                    .map(|(pos, val)| TailResponse::NextItem(pos, val))
                    .map_err(|e| e.into())
                    .then(|r| {
                        debug!("Response: {:?}", r);
                        r
                    })
                    .boxed()
            }
        }
        // futures::finished(TailResponse::NextItem(LogPos::zero(), vec![]))
    }
}

#[cfg(test)]
mod test {
    use futures::{Future, Async, task};
    use service::Service;
    use replica::LogPos;
    use store::{Store, RamStore};
    use tail::messages::*;
    use super::*;
    use std::sync::Arc;

    struct NullUnpark;

    impl task::Unpark for NullUnpark {
        fn unpark(&self) {}
    }

    fn null_parker() -> Arc<task::Unpark> {
        Arc::new(NullUnpark)
    }

    #[test]
    fn should_defer_read_from_empty_log() {
        let store = RamStore::new();
        let tail = TailService::new(store.clone());

        let mut resp = task::spawn(tail.call(TailRequest::FetchNextAfter(LogPos::zero())));

        assert_eq!(resp.poll_future(null_parker()).expect("fut"),
                   Async::NotReady)
    }

    #[test]
    fn shuold_yield_first_item_after_write() {
        let store = RamStore::new();
        let tail = TailService::new(store.clone());

        let mut resp = task::spawn(tail.call(TailRequest::FetchNextAfter(LogPos::zero())));
        let next = LogPos::zero().next();
        task::spawn(store.append_entry(LogPos::zero(), next, b"foo".to_vec()))
            .wait_future()
            .expect("append_entry 1");

        assert_eq!(resp.poll_future(null_parker()).expect("fut"),
                   Async::Ready(TailResponse::NextItem(next, b"foo".to_vec())));
    }

}
<|endoftext|>


<commit_before>// run-pass

#![feature(thread_local)]

#[thread_local]
static S: u32 = 222;

fn main() {
    let local = &S as *const u32 as usize;
    let foreign = std::thread::spawn(|| &S as *const u32 as usize).join().unwrap();
    assert_ne!(local, foreign);
}
<commit_msg>Add -O compile flag to test<commit_after>// run-pass
// compile-flags: -O

#![feature(thread_local)]

#[thread_local]
static S: u32 = 222;

fn main() {
    let local = &S as *const u32 as usize;
    let foreign = std::thread::spawn(|| &S as *const u32 as usize).join().unwrap();
    assert_ne!(local, foreign);
}
<|endoftext|>


<commit_before>// Copyright 2018 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.

//! For the NLL computation, we need to compute liveness, but only for those
//! local variables whose types contain regions. The others are not of interest
//! to us. This file defines a new index type (LiveVar) that indexes into
//! a list of "variables whose type contain regions". It also defines a map from
//! Local to LiveVar and vice versa -- this map can be given to the
//! liveness code so that it only operates over variables with regions in their
//! types, instead of all variables.

use borrow_check::nll::ToRegionVid;
use rustc::mir::{Local, Mir};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use util::liveness::LiveVariableMap;

/// Map between Local and LiveVar indices: the purpose of this
/// map is to define the subset of local variables for which we need
/// to do a liveness computation. We only need to compute whether a
/// variable `X` is live if that variable contains some region `R` in
/// its type where `R` is not known to outlive a free region (i.e.,
/// where `R` may be valid for just a subset of the fn body).
crate struct NllLivenessMap {
    /// For each local variable, contains `Some(i)` if liveness is
    /// needed for this variable.
    pub from_local: IndexVec<Local, Option<LiveVar>>,

    /// For each `LiveVar`, maps back to the original `Local` index.
    pub to_local: IndexVec<LiveVar, Local>,
}

impl LiveVariableMap for NllLivenessMap {
    fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
        self.from_local[local]
    }

    type LiveVar = LiveVar;

    fn from_live_var(&self, local: Self::LiveVar) -> Local {
        self.to_local[local]
    }

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

impl NllLivenessMap {
    crate fn compute(
        tcx: TyCtxt<'_, '_, 'tcx>,
        free_regions: &FxHashSet<RegionVid>,
        mir: &Mir<'tcx>,
    ) -> Self {
        let mut to_local = IndexVec::default();
        let from_local: IndexVec<Local, Option<_>> = mir.local_decls
            .iter_enumerated()
            .map(|(local, local_decl)| {
                if tcx.all_free_regions_meet(&local_decl.ty, |r| {
                    free_regions.contains(&r.to_region_vid())
                }) {
                    // If all the regions in the type are free regions
                    // (or there are no regions), then we don't need
                    // to track liveness for this variable.
                    None
                } else {
                    Some(to_local.push(local))
                }
            })
            .collect();

        debug!("{} total variables", mir.local_decls.len());
        debug!("{} variables need liveness", to_local.len());
        debug!("{} regions outlive free regions", free_regions.len());

        Self {
            from_local,
            to_local,
        }
    }

    /// True if there are no local variables that need liveness computation.
    crate fn is_empty(&self) -> bool {
        self.to_local.is_empty()
    }
}

/// Index given to each local variable whose type contains a region.
newtype_index!(LiveVar);
<commit_msg>improve comment on `LiveVar`<commit_after>// Copyright 2018 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.

//! For the NLL computation, we need to compute liveness, but only for those
//! local variables whose types contain regions. The others are not of interest
//! to us. This file defines a new index type (LiveVar) that indexes into
//! a list of "variables whose type contain regions". It also defines a map from
//! Local to LiveVar and vice versa -- this map can be given to the
//! liveness code so that it only operates over variables with regions in their
//! types, instead of all variables.

use borrow_check::nll::ToRegionVid;
use rustc::mir::{Local, Mir};
use rustc::ty::{RegionVid, TyCtxt};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use util::liveness::LiveVariableMap;

/// Map between Local and LiveVar indices: the purpose of this
/// map is to define the subset of local variables for which we need
/// to do a liveness computation. We only need to compute whether a
/// variable `X` is live if that variable contains some region `R` in
/// its type where `R` is not known to outlive a free region (i.e.,
/// where `R` may be valid for just a subset of the fn body).
crate struct NllLivenessMap {
    /// For each local variable, contains `Some(i)` if liveness is
    /// needed for this variable.
    pub from_local: IndexVec<Local, Option<LiveVar>>,

    /// For each `LiveVar`, maps back to the original `Local` index.
    pub to_local: IndexVec<LiveVar, Local>,
}

impl LiveVariableMap for NllLivenessMap {
    fn from_local(&self, local: Local) -> Option<Self::LiveVar> {
        self.from_local[local]
    }

    type LiveVar = LiveVar;

    fn from_live_var(&self, local: Self::LiveVar) -> Local {
        self.to_local[local]
    }

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

impl NllLivenessMap {
    crate fn compute(
        tcx: TyCtxt<'_, '_, 'tcx>,
        free_regions: &FxHashSet<RegionVid>,
        mir: &Mir<'tcx>,
    ) -> Self {
        let mut to_local = IndexVec::default();
        let from_local: IndexVec<Local, Option<_>> = mir.local_decls
            .iter_enumerated()
            .map(|(local, local_decl)| {
                if tcx.all_free_regions_meet(&local_decl.ty, |r| {
                    free_regions.contains(&r.to_region_vid())
                }) {
                    // If all the regions in the type are free regions
                    // (or there are no regions), then we don't need
                    // to track liveness for this variable.
                    None
                } else {
                    Some(to_local.push(local))
                }
            })
            .collect();

        debug!("{} total variables", mir.local_decls.len());
        debug!("{} variables need liveness", to_local.len());
        debug!("{} regions outlive free regions", free_regions.len());

        Self {
            from_local,
            to_local,
        }
    }

    /// True if there are no local variables that need liveness computation.
    crate fn is_empty(&self) -> bool {
        self.to_local.is_empty()
    }
}

/// Index given to each local variable for which we need to
/// compute liveness information. For many locals, we are able to
/// skip liveness information: for example, those variables whose
/// types contain no regions.
newtype_index!(
    LiveVar
);
<|endoftext|>


<commit_before>//! For query parameter extractor documentation, see [`Query`].

use std::{fmt, ops, sync::Arc};

use futures_util::future::{err, ok, Ready};
use serde::de;

use crate::{dev::Payload, error::QueryPayloadError, Error, FromRequest, HttpRequest};

/// Extract typed information from the request's query.
///
/// To extract typed data from the URL query string, the inner type `T` must implement the
/// [`serde::Deserialize`] trait.
///
/// Use [`QueryConfig`] to configure extraction process.
///
/// # Panics
/// A query string consists of unordered `key=value` pairs, therefore it cannot be decoded into any
/// type which depends upon data ordering (eg. tuples). Trying to do so will result in a panic.
///
/// # Examples
/// ```
/// use actix_web::{get, web};
/// use serde::Deserialize;
///
/// #[derive(Debug, Deserialize)]
/// pub enum ResponseType {
///    Token,
///    Code
/// }
///
/// #[derive(Deserialize)]
/// pub struct AuthRequest {
///    id: u64,
///    response_type: ResponseType,
/// }
///
/// // Deserialize `AuthRequest` struct from query string.
/// // This handler gets called only if the request's query parameters contain both fields.
/// // A valid request path for this handler would be `/?id=64&response_type=Code"`.
/// #[get("/")]
/// async fn index(info: web::Query<AuthRequest>) -> String {
///     format!("Authorization request for id={} and type={:?}!", info.id, info.response_type)
/// }
/// ```
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Query<T>(T);

impl<T> Query<T> {
    /// Unwrap into inner `T` value.
    pub fn into_inner(self) -> T {
        self.0
    }

    /// Deserialize `T` from a URL encoded query parameter string.
    ///
    /// ```
    /// # use std::collections::HashMap;
    /// # use actix_web::web::Query;
    /// let numbers = Query::<HashMap<String, u32>>::from_query("one=1&two=2").unwrap();
    /// assert_eq!(numbers.get("one"), Some(&1));
    /// assert_eq!(numbers.get("two"), Some(&2));
    /// assert!(numbers.get("three").is_none());
    /// ```
    pub fn from_query(query_str: &str) -> Result<Self, QueryPayloadError>
    where
        T: de::DeserializeOwned,
    {
        serde_urlencoded::from_str::<T>(query_str)
            .map(Self)
            .map_err(QueryPayloadError::Deserialize)
    }
}

impl<T> ops::Deref for Query<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> ops::DerefMut for Query<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T: fmt::Debug> fmt::Debug for Query<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T: fmt::Display> fmt::Display for Query<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// See [here](#usage) for example of usage as an extractor.
impl<T> FromRequest for Query<T>
where
    T: de::DeserializeOwned,
{
    type Error = Error;
    type Future = Ready<Result<Self, Error>>;
    type Config = QueryConfig;

    #[inline]
    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
        let error_handler = req
            .app_data::<Self::Config>()
            .map(|c| c.err_handler.clone())
            .unwrap_or(None);

        serde_urlencoded::from_str::<T>(req.query_string())
            .map(|val| ok(Query(val)))
            .unwrap_or_else(move |e| {
                let e = QueryPayloadError::Deserialize(e);

                log::debug!(
                    "Failed during Query extractor deserialization. \
                     Request path: {:?}",
                    req.path()
                );

                let e = if let Some(error_handler) = error_handler {
                    (error_handler)(e, req)
                } else {
                    e.into()
                };

                err(e)
            })
    }
}

/// Query extractor configuration.
///
/// # Examples
/// ```
/// use actix_web::{error, get, web, App, FromRequest, HttpResponse};
/// use serde::Deserialize;
///
/// #[derive(Deserialize)]
/// struct Info {
///     username: String,
/// }
///
/// /// deserialize `Info` from request's querystring
/// #[get("/")]
/// async fn index(info: web::Query<Info>) -> String {
///     format!("Welcome {}!", info.username)
/// }
///
/// // custom `Query` extractor configuration
/// let query_cfg = web::QueryConfig::default()
///     // use custom error handler
///     .error_handler(|err, req| {
///         error::InternalError::from_response(err, HttpResponse::Conflict().finish()).into()
///     });
///
/// App::new()
///     .app_data(query_cfg)
///     .service(index);
/// ```
#[derive(Clone)]
pub struct QueryConfig {
    err_handler: Option<Arc<dyn Fn(QueryPayloadError, &HttpRequest) -> Error + Send + Sync>>,
}

impl QueryConfig {
    /// Set custom error handler
    pub fn error_handler<F>(mut self, f: F) -> Self
    where
        F: Fn(QueryPayloadError, &HttpRequest) -> Error + Send + Sync + 'static,
    {
        self.err_handler = Some(Arc::new(f));
        self
    }
}

impl Default for QueryConfig {
    fn default() -> Self {
        QueryConfig { err_handler: None }
    }
}

#[cfg(test)]
mod tests {
    use actix_http::http::StatusCode;
    use derive_more::Display;
    use serde::Deserialize;

    use super::*;
    use crate::error::InternalError;
    use crate::test::TestRequest;
    use crate::HttpResponse;

    #[derive(Deserialize, Debug, Display)]
    struct Id {
        id: String,
    }

    #[actix_rt::test]
    async fn test_service_request_extract() {
        let req = TestRequest::with_uri("/name/user1/").to_srv_request();
        assert!(Query::<Id>::from_query(&req.query_string()).is_err());

        let req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
        let mut s = Query::<Id>::from_query(&req.query_string()).unwrap();

        assert_eq!(s.id, "test");
        assert_eq!(format!("{}, {:?}", s, s), "test, Id { id: \"test\" }");

        s.id = "test1".to_string();
        let s = s.into_inner();
        assert_eq!(s.id, "test1");
    }

    #[actix_rt::test]
    async fn test_request_extract() {
        let req = TestRequest::with_uri("/name/user1/").to_srv_request();
        let (req, mut pl) = req.into_parts();
        assert!(Query::<Id>::from_request(&req, &mut pl).await.is_err());

        let req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
        let (req, mut pl) = req.into_parts();

        let mut s = Query::<Id>::from_request(&req, &mut pl).await.unwrap();
        assert_eq!(s.id, "test");
        assert_eq!(format!("{}, {:?}", s, s), "test, Id { id: \"test\" }");

        s.id = "test1".to_string();
        let s = s.into_inner();
        assert_eq!(s.id, "test1");
    }

    #[actix_rt::test]
    #[should_panic]
    async fn test_tuple_panic() {
        let req = TestRequest::with_uri("/?one=1&two=2").to_srv_request();
        let (req, mut pl) = req.into_parts();

        Query::<(u32, u32)>::from_request(&req, &mut pl)
            .await
            .unwrap();
    }

    #[actix_rt::test]
    async fn test_custom_error_responder() {
        let req = TestRequest::with_uri("/name/user1/")
            .app_data(QueryConfig::default().error_handler(|e, _| {
                let resp = HttpResponse::UnprocessableEntity().finish();
                InternalError::from_response(e, resp).into()
            }))
            .to_srv_request();

        let (req, mut pl) = req.into_parts();
        let query = Query::<Id>::from_request(&req, &mut pl).await;

        assert!(query.is_err());
        assert_eq!(
            query
                .unwrap_err()
                .as_response_error()
                .error_response()
                .status(),
            StatusCode::UNPROCESSABLE_ENTITY
        );
    }
}
<commit_msg>Inner field of web::Query is public again (#2016) (#2017)<commit_after>//! For query parameter extractor documentation, see [`Query`].

use std::{fmt, ops, sync::Arc};

use futures_util::future::{err, ok, Ready};
use serde::de;

use crate::{dev::Payload, error::QueryPayloadError, Error, FromRequest, HttpRequest};

/// Extract typed information from the request's query.
///
/// To extract typed data from the URL query string, the inner type `T` must implement the
/// [`serde::Deserialize`] trait.
///
/// Use [`QueryConfig`] to configure extraction process.
///
/// # Panics
/// A query string consists of unordered `key=value` pairs, therefore it cannot be decoded into any
/// type which depends upon data ordering (eg. tuples). Trying to do so will result in a panic.
///
/// # Examples
/// ```
/// use actix_web::{get, web};
/// use serde::Deserialize;
///
/// #[derive(Debug, Deserialize)]
/// pub enum ResponseType {
///    Token,
///    Code
/// }
///
/// #[derive(Debug, Deserialize)]
/// pub struct AuthRequest {
///    id: u64,
///    response_type: ResponseType,
/// }
///
/// // Deserialize `AuthRequest` struct from query string.
/// // This handler gets called only if the request's query parameters contain both fields.
/// // A valid request path for this handler would be `/?id=64&response_type=Code"`.
/// #[get("/")]
/// async fn index(info: web::Query<AuthRequest>) -> String {
///     format!("Authorization request for id={} and type={:?}!", info.id, info.response_type)
/// }
///
/// // To access the entire underlying query struct, use `.into_inner()`.
/// #[get("/debug1")]
/// async fn debug1(info: web::Query<AuthRequest>) -> String {
///     dbg!("Authorization object={:?}", info.into_inner());
///     "OK".to_string()
/// }
///
/// // Or use `.0`, which is equivalent to `.into_inner()`.
/// #[get("/debug2")]
/// async fn debug2(info: web::Query<AuthRequest>) -> String {
///     dbg!("Authorization object={:?}", info.0);
///     "OK".to_string()
/// }
/// ```
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Query<T>(pub T);

impl<T> Query<T> {
    /// Unwrap into inner `T` value.
    pub fn into_inner(self) -> T {
        self.0
    }

    /// Deserialize `T` from a URL encoded query parameter string.
    ///
    /// ```
    /// # use std::collections::HashMap;
    /// # use actix_web::web::Query;
    /// let numbers = Query::<HashMap<String, u32>>::from_query("one=1&two=2").unwrap();
    /// assert_eq!(numbers.get("one"), Some(&1));
    /// assert_eq!(numbers.get("two"), Some(&2));
    /// assert!(numbers.get("three").is_none());
    /// ```
    pub fn from_query(query_str: &str) -> Result<Self, QueryPayloadError>
    where
        T: de::DeserializeOwned,
    {
        serde_urlencoded::from_str::<T>(query_str)
            .map(Self)
            .map_err(QueryPayloadError::Deserialize)
    }
}

impl<T> ops::Deref for Query<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

impl<T> ops::DerefMut for Query<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.0
    }
}

impl<T: fmt::Debug> fmt::Debug for Query<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

impl<T: fmt::Display> fmt::Display for Query<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.0.fmt(f)
    }
}

/// See [here](#usage) for example of usage as an extractor.
impl<T> FromRequest for Query<T>
where
    T: de::DeserializeOwned,
{
    type Error = Error;
    type Future = Ready<Result<Self, Error>>;
    type Config = QueryConfig;

    #[inline]
    fn from_request(req: &HttpRequest, _: &mut Payload) -> Self::Future {
        let error_handler = req
            .app_data::<Self::Config>()
            .map(|c| c.err_handler.clone())
            .unwrap_or(None);

        serde_urlencoded::from_str::<T>(req.query_string())
            .map(|val| ok(Query(val)))
            .unwrap_or_else(move |e| {
                let e = QueryPayloadError::Deserialize(e);

                log::debug!(
                    "Failed during Query extractor deserialization. \
                     Request path: {:?}",
                    req.path()
                );

                let e = if let Some(error_handler) = error_handler {
                    (error_handler)(e, req)
                } else {
                    e.into()
                };

                err(e)
            })
    }
}

/// Query extractor configuration.
///
/// # Examples
/// ```
/// use actix_web::{error, get, web, App, FromRequest, HttpResponse};
/// use serde::Deserialize;
///
/// #[derive(Deserialize)]
/// struct Info {
///     username: String,
/// }
///
/// /// deserialize `Info` from request's querystring
/// #[get("/")]
/// async fn index(info: web::Query<Info>) -> String {
///     format!("Welcome {}!", info.username)
/// }
///
/// // custom `Query` extractor configuration
/// let query_cfg = web::QueryConfig::default()
///     // use custom error handler
///     .error_handler(|err, req| {
///         error::InternalError::from_response(err, HttpResponse::Conflict().finish()).into()
///     });
///
/// App::new()
///     .app_data(query_cfg)
///     .service(index);
/// ```
#[derive(Clone)]
pub struct QueryConfig {
    err_handler: Option<Arc<dyn Fn(QueryPayloadError, &HttpRequest) -> Error + Send + Sync>>,
}

impl QueryConfig {
    /// Set custom error handler
    pub fn error_handler<F>(mut self, f: F) -> Self
    where
        F: Fn(QueryPayloadError, &HttpRequest) -> Error + Send + Sync + 'static,
    {
        self.err_handler = Some(Arc::new(f));
        self
    }
}

impl Default for QueryConfig {
    fn default() -> Self {
        QueryConfig { err_handler: None }
    }
}

#[cfg(test)]
mod tests {
    use actix_http::http::StatusCode;
    use derive_more::Display;
    use serde::Deserialize;

    use super::*;
    use crate::error::InternalError;
    use crate::test::TestRequest;
    use crate::HttpResponse;

    #[derive(Deserialize, Debug, Display)]
    struct Id {
        id: String,
    }

    #[actix_rt::test]
    async fn test_service_request_extract() {
        let req = TestRequest::with_uri("/name/user1/").to_srv_request();
        assert!(Query::<Id>::from_query(&req.query_string()).is_err());

        let req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
        let mut s = Query::<Id>::from_query(&req.query_string()).unwrap();

        assert_eq!(s.id, "test");
        assert_eq!(format!("{}, {:?}", s, s), "test, Id { id: \"test\" }");

        s.id = "test1".to_string();
        let s = s.into_inner();
        assert_eq!(s.id, "test1");
    }

    #[actix_rt::test]
    async fn test_request_extract() {
        let req = TestRequest::with_uri("/name/user1/").to_srv_request();
        let (req, mut pl) = req.into_parts();
        assert!(Query::<Id>::from_request(&req, &mut pl).await.is_err());

        let req = TestRequest::with_uri("/name/user1/?id=test").to_srv_request();
        let (req, mut pl) = req.into_parts();

        let mut s = Query::<Id>::from_request(&req, &mut pl).await.unwrap();
        assert_eq!(s.id, "test");
        assert_eq!(format!("{}, {:?}", s, s), "test, Id { id: \"test\" }");

        s.id = "test1".to_string();
        let s = s.into_inner();
        assert_eq!(s.id, "test1");
    }

    #[actix_rt::test]
    #[should_panic]
    async fn test_tuple_panic() {
        let req = TestRequest::with_uri("/?one=1&two=2").to_srv_request();
        let (req, mut pl) = req.into_parts();

        Query::<(u32, u32)>::from_request(&req, &mut pl)
            .await
            .unwrap();
    }

    #[actix_rt::test]
    async fn test_custom_error_responder() {
        let req = TestRequest::with_uri("/name/user1/")
            .app_data(QueryConfig::default().error_handler(|e, _| {
                let resp = HttpResponse::UnprocessableEntity().finish();
                InternalError::from_response(e, resp).into()
            }))
            .to_srv_request();

        let (req, mut pl) = req.into_parts();
        let query = Query::<Id>::from_request(&req, &mut pl).await;

        assert!(query.is_err());
        assert_eq!(
            query
                .unwrap_err()
                .as_response_error()
                .error_response()
                .status(),
            StatusCode::UNPROCESSABLE_ENTITY
        );
    }
}
<|endoftext|>


<commit_before>use std::{cmp::Ordering, marker::PhantomData, mem::MaybeUninit, time::Duration};

/// Marker for clock source that never returns a negative [`Time`]
pub trait NonNegativeClockSource: ClockSource {}

/// Monotonic clock
#[derive(Debug)]
pub struct Monotonic;

impl ClockSource for Monotonic {
    fn id() -> libc::clockid_t {
        libc::CLOCK_MONOTONIC
    }
}

impl NonNegativeClockSource for Monotonic {}

/// Clock based on boottime
#[derive(Debug)]
pub struct Boottime;

impl ClockSource for Boottime {
    fn id() -> libc::clockid_t {
        libc::CLOCK_BOOTTIME
    }
}

impl NonNegativeClockSource for Boottime {}

/// Realtime clock
#[derive(Debug)]
pub struct Realtime;

impl ClockSource for Realtime {
    fn id() -> libc::clockid_t {
        libc::CLOCK_REALTIME
    }
}

/// Id for a clock according to unix clockid_t
pub trait ClockSource {
    /// Gets the id of the clock source
    fn id() -> libc::clockid_t;
}

/// Defines a clock with a specific kind
#[derive(Debug)]
pub struct Clock<Kind> {
    clk_id: libc::clockid_t,
    _kind: PhantomData<Kind>,
}

impl<Kind: ClockSource> Clock<Kind> {
    /// Initialize a new clock
    pub fn new() -> std::io::Result<Self> {
        let clk_id = Kind::id();
        clock_get_time(clk_id)?;
        Ok(Clock {
            clk_id,
            _kind: PhantomData,
        })
    }

    /// Returns the current time
    pub fn now(&self) -> Time<Kind> {
        clock_get_time(self.clk_id)
            .expect("failed to get clock time")
            .into()
    }

    /// Gets the id of the clock
    pub fn id(&self) -> libc::clockid_t {
        Kind::id()
    }
}

/// A point in time for a clock with a specific kind
pub struct Time<Kind> {
    tp: libc::timespec,
    _kind: PhantomData<Kind>,
}

impl<Kind> Time<Kind> {
    /// Gets the duration between self and a later time
    pub fn duration_since(&self, later: Time<Kind>) -> Duration {
        saturating_sub_timespec(later.tp, self.tp).unwrap_or(Duration::ZERO)
    }
}

impl<Kind> Clone for Time<Kind> {
    fn clone(&self) -> Self {
        Self {
            tp: self.tp,
            _kind: self._kind,
        }
    }
}

impl<Kind> Copy for Time<Kind> {}

impl<Kind: NonNegativeClockSource> From<Time<Kind>> for Duration {
    fn from(time: Time<Kind>) -> Self {
        debug_assert!(time.tp.tv_sec > 0);
        debug_assert!(time.tp.tv_nsec > 0);
        Duration::new(time.tp.tv_sec as u64, time.tp.tv_nsec as u32)
    }
}

impl<Kind> std::fmt::Debug for Time<Kind> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Time")
            .field("tp", &self.tp)
            .field("kind", &self._kind)
            .finish()
    }
}

impl<Kind> PartialEq for Time<Kind> {
    fn eq(&self, other: &Self) -> bool {
        self.tp == other.tp && self._kind == other._kind
    }
}

impl<Kind> Eq for Time<Kind> {}

impl<Kind> PartialOrd for Time<Kind> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<Kind> Ord for Time<Kind> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        let tv_sec = self.tp.tv_sec.cmp(&other.tp.tv_sec);

        if tv_sec == Ordering::Equal {
            self.tp.tv_nsec.cmp(&other.tp.tv_nsec)
        } else {
            tv_sec
        }
    }
}

impl<Kind: NonNegativeClockSource> From<Duration> for Time<Kind> {
    fn from(tp: Duration) -> Self {
        let tp = libc::timespec {
            tv_sec: tp.as_secs() as libc::time_t,
            #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
            tv_nsec: tp.subsec_nanos() as i64,
            #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
            tv_nsec: tp.subsec_nanos() as std::os::raw::c_long,
        };
        Time {
            tp,
            _kind: PhantomData,
        }
    }
}

impl<Kind> From<libc::timespec> for Time<Kind> {
    fn from(tp: libc::timespec) -> Self {
        Time {
            tp,
            _kind: PhantomData,
        }
    }
}

const NANOS_PER_SEC: i64 = 1_000_000_000;

fn saturating_sub_timespec(lhs: libc::timespec, rhs: libc::timespec) -> Option<Duration> {
    if let Some(mut secs) = lhs.tv_sec.checked_sub(rhs.tv_sec) {
        let nanos = if lhs.tv_nsec >= rhs.tv_nsec {
            lhs.tv_nsec - rhs.tv_nsec
        } else if let Some(sub_secs) = secs.checked_sub(1) {
            secs = sub_secs;
            lhs.tv_nsec + NANOS_PER_SEC - rhs.tv_nsec
        } else {
            return None;
        };
        debug_assert!(nanos < NANOS_PER_SEC);
        Some(Duration::new(secs as u64, nanos as u32))
    } else {
        None
    }
}

fn clock_get_time(clk_id: libc::clockid_t) -> Result<libc::timespec, std::io::Error> {
    let mut tp = MaybeUninit::zeroed();
    unsafe {
        let res = libc::clock_gettime(clk_id, tp.as_mut_ptr());

        if res < 0 {
            return Err(std::io::Error::last_os_error());
        }

        Ok(tp.assume_init())
    }
}

#[cfg(test)]
mod test {
    use std::time::Duration;

    use crate::utils::{Boottime, Clock, Monotonic, Time};

    #[test]
    fn monotonic() {
        let clock_source: Clock<Monotonic> = Clock::new().unwrap();
        let now = clock_source.now();
        let zero = Time::<Monotonic>::from(Duration::ZERO);
        assert_eq!(zero.duration_since(now), now.into());
    }

    #[test]
    fn boottime() {
        let clock_source: Clock<Boottime> = Clock::new().unwrap();
        let now = clock_source.now();
        let zero = Time::<Boottime>::from(Duration::ZERO);
        assert_eq!(zero.duration_since(now), now.into());
    }
}
<commit_msg>utils: clock tv_nsec uses a platform dependant type<commit_after>use std::{cmp::Ordering, marker::PhantomData, mem::MaybeUninit, time::Duration};

/// Marker for clock source that never returns a negative [`Time`]
pub trait NonNegativeClockSource: ClockSource {}

/// Monotonic clock
#[derive(Debug)]
pub struct Monotonic;

impl ClockSource for Monotonic {
    fn id() -> libc::clockid_t {
        libc::CLOCK_MONOTONIC
    }
}

impl NonNegativeClockSource for Monotonic {}

/// Clock based on boottime
#[derive(Debug)]
pub struct Boottime;

impl ClockSource for Boottime {
    fn id() -> libc::clockid_t {
        libc::CLOCK_BOOTTIME
    }
}

impl NonNegativeClockSource for Boottime {}

/// Realtime clock
#[derive(Debug)]
pub struct Realtime;

impl ClockSource for Realtime {
    fn id() -> libc::clockid_t {
        libc::CLOCK_REALTIME
    }
}

/// Id for a clock according to unix clockid_t
pub trait ClockSource {
    /// Gets the id of the clock source
    fn id() -> libc::clockid_t;
}

/// Defines a clock with a specific kind
#[derive(Debug)]
pub struct Clock<Kind> {
    clk_id: libc::clockid_t,
    _kind: PhantomData<Kind>,
}

impl<Kind: ClockSource> Clock<Kind> {
    /// Initialize a new clock
    pub fn new() -> std::io::Result<Self> {
        let clk_id = Kind::id();
        clock_get_time(clk_id)?;
        Ok(Clock {
            clk_id,
            _kind: PhantomData,
        })
    }

    /// Returns the current time
    pub fn now(&self) -> Time<Kind> {
        clock_get_time(self.clk_id)
            .expect("failed to get clock time")
            .into()
    }

    /// Gets the id of the clock
    pub fn id(&self) -> libc::clockid_t {
        Kind::id()
    }
}

/// A point in time for a clock with a specific kind
pub struct Time<Kind> {
    tp: libc::timespec,
    _kind: PhantomData<Kind>,
}

impl<Kind> Time<Kind> {
    /// Gets the duration between self and a later time
    pub fn duration_since(&self, later: Time<Kind>) -> Duration {
        saturating_sub_timespec(later.tp, self.tp).unwrap_or(Duration::ZERO)
    }
}

impl<Kind> Clone for Time<Kind> {
    fn clone(&self) -> Self {
        Self {
            tp: self.tp,
            _kind: self._kind,
        }
    }
}

impl<Kind> Copy for Time<Kind> {}

impl<Kind: NonNegativeClockSource> From<Time<Kind>> for Duration {
    fn from(time: Time<Kind>) -> Self {
        debug_assert!(time.tp.tv_sec > 0);
        debug_assert!(time.tp.tv_nsec > 0);
        Duration::new(time.tp.tv_sec as u64, time.tp.tv_nsec as u32)
    }
}

impl<Kind> std::fmt::Debug for Time<Kind> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("Time")
            .field("tp", &self.tp)
            .field("kind", &self._kind)
            .finish()
    }
}

impl<Kind> PartialEq for Time<Kind> {
    fn eq(&self, other: &Self) -> bool {
        self.tp == other.tp && self._kind == other._kind
    }
}

impl<Kind> Eq for Time<Kind> {}

impl<Kind> PartialOrd for Time<Kind> {
    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
        Some(self.cmp(other))
    }
}

impl<Kind> Ord for Time<Kind> {
    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
        let tv_sec = self.tp.tv_sec.cmp(&other.tp.tv_sec);

        if tv_sec == Ordering::Equal {
            self.tp.tv_nsec.cmp(&other.tp.tv_nsec)
        } else {
            tv_sec
        }
    }
}

impl<Kind: NonNegativeClockSource> From<Duration> for Time<Kind> {
    fn from(tp: Duration) -> Self {
        let tp = libc::timespec {
            tv_sec: tp.as_secs() as libc::time_t,
            #[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
            tv_nsec: tp.subsec_nanos() as i64,
            #[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
            tv_nsec: tp.subsec_nanos() as std::os::raw::c_long,
        };
        Time {
            tp,
            _kind: PhantomData,
        }
    }
}

impl<Kind> From<libc::timespec> for Time<Kind> {
    fn from(tp: libc::timespec) -> Self {
        Time {
            tp,
            _kind: PhantomData,
        }
    }
}

#[cfg(all(target_arch = "x86_64", target_pointer_width = "32"))]
const NANOS_PER_SEC: i64 = 1_000_000_000;

#[cfg(not(all(target_arch = "x86_64", target_pointer_width = "32")))]
const NANOS_PER_SEC: std::os::raw::c_long = 1_000_000_000;

fn saturating_sub_timespec(lhs: libc::timespec, rhs: libc::timespec) -> Option<Duration> {
    if let Some(mut secs) = lhs.tv_sec.checked_sub(rhs.tv_sec) {
        let nanos = if lhs.tv_nsec >= rhs.tv_nsec {
            lhs.tv_nsec - rhs.tv_nsec
        } else if let Some(sub_secs) = secs.checked_sub(1) {
            secs = sub_secs;
            lhs.tv_nsec + NANOS_PER_SEC - rhs.tv_nsec
        } else {
            return None;
        };
        debug_assert!(nanos < NANOS_PER_SEC);
        Some(Duration::new(secs as u64, nanos as u32))
    } else {
        None
    }
}

fn clock_get_time(clk_id: libc::clockid_t) -> Result<libc::timespec, std::io::Error> {
    let mut tp = MaybeUninit::zeroed();
    unsafe {
        let res = libc::clock_gettime(clk_id, tp.as_mut_ptr());

        if res < 0 {
            return Err(std::io::Error::last_os_error());
        }

        Ok(tp.assume_init())
    }
}

#[cfg(test)]
mod test {
    use std::time::Duration;

    use crate::utils::{Boottime, Clock, Monotonic, Time};

    #[test]
    fn monotonic() {
        let clock_source: Clock<Monotonic> = Clock::new().unwrap();
        let now = clock_source.now();
        let zero = Time::<Monotonic>::from(Duration::ZERO);
        assert_eq!(zero.duration_since(now), now.into());
    }

    #[test]
    fn boottime() {
        let clock_source: Clock<Boottime> = Clock::new().unwrap();
        let now = clock_source.now();
        let zero = Time::<Boottime>::from(Duration::ZERO);
        assert_eq!(zero.duration_since(now), now.into());
    }
}
<|endoftext|>


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

use dom::bindings::codegen::BindingDeclarations::HTMLButtonElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLButtonElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLButtonElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::htmlformelement::HTMLFormElement;
use dom::node::{Node, ElementNodeTypeId, window_from_node};
use dom::validitystate::ValidityState;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLButtonElement {
    pub htmlelement: HTMLElement
}

impl HTMLButtonElementDerived for EventTarget {
    fn is_htmlbuttonelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLButtonElementTypeId))
    }
}

impl HTMLButtonElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLButtonElement {
        HTMLButtonElement {
            htmlelement: HTMLElement::new_inherited(HTMLButtonElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLButtonElement> {
        let element = HTMLButtonElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLButtonElementBinding::Wrap)
    }
}

pub trait HTMLButtonElementMethods {
    fn Autofocus(&self) -> bool;
    fn SetAutofocus(&mut self, _autofocus: bool) -> ErrorResult;
    fn Disabled(&self) -> bool;
    fn SetDisabled(&mut self, _disabled: bool) -> ErrorResult;
    fn GetForm(&self) -> Option<Temporary<HTMLFormElement>>;
    fn FormAction(&self) -> DOMString;
    fn SetFormAction(&mut self, _formaction: DOMString) -> ErrorResult;
    fn FormEnctype(&self) -> DOMString;
    fn SetFormEnctype(&mut self, _formenctype: DOMString) -> ErrorResult;
    fn FormMethod(&self) -> DOMString;
    fn SetFormMethod(&mut self, _formmethod: DOMString) -> ErrorResult;
    fn FormNoValidate(&self) -> bool;
    fn SetFormNoValidate(&mut self, _novalidate: bool) -> ErrorResult;
    fn FormTarget(&self) -> DOMString;
    fn SetFormTarget(&mut self, _formtarget: DOMString) -> ErrorResult;
    fn Name(&self) -> DOMString;
    fn SetName(&mut self, _name: DOMString) -> ErrorResult;
    fn Type(&self) -> DOMString;
    fn SetType(&mut self, _type: DOMString) -> ErrorResult;
    fn Value(&self) -> DOMString;
    fn SetValue(&mut self, _value: DOMString) -> ErrorResult;
    fn WillValidate(&self) -> bool;
    fn SetWillValidate(&mut self, _will_validate: bool);
    fn Validity(&self) -> Temporary<ValidityState>;
    fn ValidationMessage(&self) -> DOMString;
    fn SetValidationMessage(&mut self, _message: DOMString) -> ErrorResult;
    fn CheckValidity(&self) -> bool;
    fn SetCustomValidity(&mut self, _error: DOMString);
}

impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
    fn Autofocus(&self) -> bool {
        false
    }

    fn SetAutofocus(&mut self, _autofocus: bool) -> ErrorResult {
        Ok(())
    }

    fn Disabled(&self) -> bool {
        false
    }

    fn SetDisabled(&mut self, _disabled: bool) -> ErrorResult {
        Ok(())
    }

    fn GetForm(&self) -> Option<Temporary<HTMLFormElement>> {
        None
    }

    fn FormAction(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFormAction(&mut self, _formaction: DOMString) -> ErrorResult {
        Ok(())
    }

    fn FormEnctype(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFormEnctype(&mut self, _formenctype: DOMString) -> ErrorResult {
        Ok(())
    }

    fn FormMethod(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFormMethod(&mut self, _formmethod: DOMString) -> ErrorResult {
        Ok(())
    }

    fn FormNoValidate(&self) -> bool {
        false
    }

    fn SetFormNoValidate(&mut self, _novalidate: bool) -> ErrorResult {
        Ok(())
    }

    fn FormTarget(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFormTarget(&mut self, _formtarget: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Name(&self) -> DOMString {
        "".to_owned()
    }

    fn SetName(&mut self, _name: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Type(&self) -> DOMString {
        "".to_owned()
    }

    fn SetType(&mut self, _type: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Value(&self) -> DOMString {
        "".to_owned()
    }

    fn SetValue(&mut self, _value: DOMString) -> ErrorResult {
        Ok(())
    }

    fn WillValidate(&self) -> bool {
        false
    }

    fn SetWillValidate(&mut self, _will_validate: bool) {
    }

    fn Validity(&self) -> Temporary<ValidityState> {
        let window = window_from_node(self).root();
        ValidityState::new(&*window)
    }

    fn ValidationMessage(&self) -> DOMString {
        "".to_owned()
    }

    fn SetValidationMessage(&mut self, _message: DOMString) -> ErrorResult {
        Ok(())
    }

    fn CheckValidity(&self) -> bool {
        true
    }

    fn SetCustomValidity(&mut self, _error: DOMString) {
    }
}
<commit_msg>Remove needless '&mut self' from HTMLButtonElementMethods.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::BindingDeclarations::HTMLButtonElementBinding;
use dom::bindings::codegen::InheritTypes::HTMLButtonElementDerived;
use dom::bindings::js::{JSRef, Temporary};
use dom::bindings::error::ErrorResult;
use dom::document::Document;
use dom::element::HTMLButtonElementTypeId;
use dom::eventtarget::{EventTarget, NodeTargetTypeId};
use dom::htmlelement::HTMLElement;
use dom::htmlformelement::HTMLFormElement;
use dom::node::{Node, ElementNodeTypeId, window_from_node};
use dom::validitystate::ValidityState;
use servo_util::str::DOMString;

#[deriving(Encodable)]
pub struct HTMLButtonElement {
    pub htmlelement: HTMLElement
}

impl HTMLButtonElementDerived for EventTarget {
    fn is_htmlbuttonelement(&self) -> bool {
        self.type_id == NodeTargetTypeId(ElementNodeTypeId(HTMLButtonElementTypeId))
    }
}

impl HTMLButtonElement {
    pub fn new_inherited(localName: DOMString, document: &JSRef<Document>) -> HTMLButtonElement {
        HTMLButtonElement {
            htmlelement: HTMLElement::new_inherited(HTMLButtonElementTypeId, localName, document)
        }
    }

    pub fn new(localName: DOMString, document: &JSRef<Document>) -> Temporary<HTMLButtonElement> {
        let element = HTMLButtonElement::new_inherited(localName, document);
        Node::reflect_node(box element, document, HTMLButtonElementBinding::Wrap)
    }
}

pub trait HTMLButtonElementMethods {
    fn Autofocus(&self) -> bool;
    fn SetAutofocus(&self, _autofocus: bool) -> ErrorResult;
    fn Disabled(&self) -> bool;
    fn SetDisabled(&self, _disabled: bool) -> ErrorResult;
    fn GetForm(&self) -> Option<Temporary<HTMLFormElement>>;
    fn FormAction(&self) -> DOMString;
    fn SetFormAction(&self, _formaction: DOMString) -> ErrorResult;
    fn FormEnctype(&self) -> DOMString;
    fn SetFormEnctype(&self, _formenctype: DOMString) -> ErrorResult;
    fn FormMethod(&self) -> DOMString;
    fn SetFormMethod(&self, _formmethod: DOMString) -> ErrorResult;
    fn FormNoValidate(&self) -> bool;
    fn SetFormNoValidate(&self, _novalidate: bool) -> ErrorResult;
    fn FormTarget(&self) -> DOMString;
    fn SetFormTarget(&self, _formtarget: DOMString) -> ErrorResult;
    fn Name(&self) -> DOMString;
    fn SetName(&self, _name: DOMString) -> ErrorResult;
    fn Type(&self) -> DOMString;
    fn SetType(&self, _type: DOMString) -> ErrorResult;
    fn Value(&self) -> DOMString;
    fn SetValue(&self, _value: DOMString) -> ErrorResult;
    fn WillValidate(&self) -> bool;
    fn SetWillValidate(&self, _will_validate: bool);
    fn Validity(&self) -> Temporary<ValidityState>;
    fn ValidationMessage(&self) -> DOMString;
    fn SetValidationMessage(&self, _message: DOMString) -> ErrorResult;
    fn CheckValidity(&self) -> bool;
    fn SetCustomValidity(&self, _error: DOMString);
}

impl<'a> HTMLButtonElementMethods for JSRef<'a, HTMLButtonElement> {
    fn Autofocus(&self) -> bool {
        false
    }

    fn SetAutofocus(&self, _autofocus: bool) -> ErrorResult {
        Ok(())
    }

    fn Disabled(&self) -> bool {
        false
    }

    fn SetDisabled(&self, _disabled: bool) -> ErrorResult {
        Ok(())
    }

    fn GetForm(&self) -> Option<Temporary<HTMLFormElement>> {
        None
    }

    fn FormAction(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFormAction(&self, _formaction: DOMString) -> ErrorResult {
        Ok(())
    }

    fn FormEnctype(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFormEnctype(&self, _formenctype: DOMString) -> ErrorResult {
        Ok(())
    }

    fn FormMethod(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFormMethod(&self, _formmethod: DOMString) -> ErrorResult {
        Ok(())
    }

    fn FormNoValidate(&self) -> bool {
        false
    }

    fn SetFormNoValidate(&self, _novalidate: bool) -> ErrorResult {
        Ok(())
    }

    fn FormTarget(&self) -> DOMString {
        "".to_owned()
    }

    fn SetFormTarget(&self, _formtarget: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Name(&self) -> DOMString {
        "".to_owned()
    }

    fn SetName(&self, _name: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Type(&self) -> DOMString {
        "".to_owned()
    }

    fn SetType(&self, _type: DOMString) -> ErrorResult {
        Ok(())
    }

    fn Value(&self) -> DOMString {
        "".to_owned()
    }

    fn SetValue(&self, _value: DOMString) -> ErrorResult {
        Ok(())
    }

    fn WillValidate(&self) -> bool {
        false
    }

    fn SetWillValidate(&self, _will_validate: bool) {
    }

    fn Validity(&self) -> Temporary<ValidityState> {
        let window = window_from_node(self).root();
        ValidityState::new(&*window)
    }

    fn ValidationMessage(&self) -> DOMString {
        "".to_owned()
    }

    fn SetValidationMessage(&self, _message: DOMString) -> ErrorResult {
        Ok(())
    }

    fn CheckValidity(&self) -> bool {
        true
    }

    fn SetCustomValidity(&self, _error: DOMString) {
    }
}
<|endoftext|>


<commit_before>#![cfg_attr(loom, allow(dead_code, unreachable_pub, unused_imports))]

//! Future-aware synchronization
//!
//! This module is enabled with the **`sync`** feature flag.
//!
//! Tasks sometimes need to communicate with each other. This module contains
//! two basic abstractions for doing so:
//!
//! - [oneshot](oneshot/index.html), a way of sending a single value
//!   from one task to another.
//! - [mpsc](mpsc/index.html), a multi-producer, single-consumer channel for
//!   sending values between tasks.
//! - [`Mutex`](struct.Mutex.html), an asynchronous `Mutex`-like type.
//! - [watch](watch/index.html), a single-producer, multi-consumer channel that
//!   only stores the **most recently** sent value.

cfg_sync! {
    mod barrier;
    pub use barrier::{Barrier, BarrierWaitResult};

    pub mod mpsc;

    mod mutex;
    pub use mutex::{Mutex, MutexGuard};

    pub mod oneshot;

    pub(crate) mod semaphore;

    mod task;
    pub(crate) use task::AtomicWaker;

    pub mod watch;
}

cfg_not_sync! {
    cfg_atomic_waker_impl! {
        mod task;
        pub(crate) use task::AtomicWaker;
    }

    #[cfg(any(
            feature = "rt-core",
            feature = "process",
            feature = "signal"))]
    pub(crate) mod oneshot;

    cfg_signal! {
        pub(crate) mod mpsc;
        pub(crate) mod semaphore;
    }
}

/// Unit tests
#[cfg(test)]
mod tests;
<commit_msg>Fix typo in sync documentation (#1942)<commit_after>#![cfg_attr(loom, allow(dead_code, unreachable_pub, unused_imports))]

//! Future-aware synchronization
//!
//! This module is enabled with the **`sync`** feature flag.
//!
//! Tasks sometimes need to communicate with each other. This module contains
//! basic abstractions for doing so:
//!
//! - [oneshot](oneshot/index.html), a way of sending a single value
//!   from one task to another.
//! - [mpsc](mpsc/index.html), a multi-producer, single-consumer channel for
//!   sending values between tasks.
//! - [`Mutex`](struct.Mutex.html), an asynchronous `Mutex`-like type.
//! - [watch](watch/index.html), a single-producer, multi-consumer channel that
//!   only stores the **most recently** sent value.

cfg_sync! {
    mod barrier;
    pub use barrier::{Barrier, BarrierWaitResult};

    pub mod mpsc;

    mod mutex;
    pub use mutex::{Mutex, MutexGuard};

    pub mod oneshot;

    pub(crate) mod semaphore;

    mod task;
    pub(crate) use task::AtomicWaker;

    pub mod watch;
}

cfg_not_sync! {
    cfg_atomic_waker_impl! {
        mod task;
        pub(crate) use task::AtomicWaker;
    }

    #[cfg(any(
            feature = "rt-core",
            feature = "process",
            feature = "signal"))]
    pub(crate) mod oneshot;

    cfg_signal! {
        pub(crate) mod mpsc;
        pub(crate) mod semaphore;
    }
}

/// Unit tests
#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>extern crate clipboard_win;

use clipboard_win::{set_clipboard, ClipboardManager};
use std::process::Command;

///Trimm all lines in string.
///Return None if string is not changed.
fn trim_lines(text: &String) -> Option<String> {
    let orig_len = text.len();
    let last_char = text.chars().last().unwrap();
    let mut text = text.lines().fold(String::new(), |acc, line| acc + line.trim_right() + "\n");

    if last_char != '\n' {
        text.pop();
    }

    if orig_len == text.len() { return None; }
    Some(text)
}

fn handler_clip_text(text: &String) {
    if text.len() == 0 { return; }

    if text.starts_with("wget") {
        println!("wget download:");
        let status = Command::new("powershell").arg("-Command").arg(format!("cd D:/Downloads; {}", &text)).status().unwrap();
        if !status.success() {
            println!("Failed to run wget.");
        }
        return;
    }

    println!("Clipboard content:\n{}", &text);
    if let Some(trim_text) = trim_lines(&text) {
        if set_clipboard(&trim_text).is_err() {
            println!("Failed to update clipboard");
        }
    }
}

fn main() {
    println!("Clipboard monitor");
    ClipboardManager::new().ok_callback(handler_clip_text).run();
}
<commit_msg>clipboard_monitor: parallel download<commit_after>extern crate clipboard_win;

use clipboard_win::{set_clipboard, ClipboardManager};
use std::process::Command;

#[inline(always)]
fn find_file_name(text: &String) -> String {
    let left: usize = text.rfind("-O \"").unwrap_or(0);
    let right: usize = text.rfind("\" -c").unwrap_or(0);

    if left == right { return "UNKNOWN".to_string(); }
    let left: usize = left + 4;
    text[left..right].to_string()
}

///Trimm all lines in string.
///Return None if string is not changed.
fn trim_lines(text: &String) -> Option<String> {
    let orig_len = text.len();
    let last_char = text.chars().last().unwrap();
    let mut text = text.lines().fold(String::new(), |acc, line| acc + line.trim_right() + "\n");

    if last_char != '\n' {
        text.pop();
    }

    if orig_len == text.len() { return None; }
    Some(text)
}

fn handler_clip_text(text: &String) {
    if text.len() == 0 { return; }

    if text.starts_with("wget") {
        let file_name = find_file_name(&text);
        println!(">>>wget {}", &file_name);

        let cmd = format!("cd E:/Downloads; {}", text);
        if std::thread::Builder::new().name(file_name).spawn(move || {
            let output = Command::new("powershell").arg("-Command").arg(cmd).output().unwrap();
            if !output.status.success() {
                println!("[{}] Failed to wget:\n{}", std::thread::current().name().unwrap_or("UNKNOWN"), String::from_utf8_lossy(&output.stdout));
            }
            else {
                println!("[{}] Successfully downloaded", std::thread::current().name().unwrap_or("UNKNOWN"));
            }
        }).is_err() {
            println!("Failed to run new thread with wget");
        }
        return;
    }

    println!("Clipboard content:\n{}", &text);
    if let Some(trim_text) = trim_lines(&text) {
        if set_clipboard(&trim_text).is_err() {
            println!("Failed to update clipboard");
        }
    }
}

fn main() {
    println!("Clipboard monitor");
    ClipboardManager::new().ok_callback(handler_clip_text).run();
}
<|endoftext|>


<commit_before>//! Reject certain requests as instance load reaches capacity.
//!
//! The primary goal of this middleware is to avoid starving the download endpoint of resources.
//! When bots send many parallel requests that run slow database queries, download requests may
//! block and eventually timeout waiting for a database connection.
//!
//! Bots must continue to respect our crawler policy, but until we can manually block bad clients
//! we should avoid dropping download requests even if that means rejecting some legitimate
//! requests to other endpoints.

use std::sync::atomic::{AtomicUsize, Ordering};

use super::prelude::*;
use conduit::{RequestExt, StatusCode};

#[derive(Default)]
pub(super) struct BalanceCapacity {
    handler: Option<Box<dyn Handler>>,
    capacity: usize,
    in_flight_requests: AtomicUsize,
    log_at_percentage: usize,
    throttle_at_percentage: usize,
    dl_only_at_percentage: usize,
}

impl BalanceCapacity {
    pub fn new(capacity: usize) -> Self {
        Self {
            handler: None,
            capacity,
            in_flight_requests: AtomicUsize::new(0),
            log_at_percentage: read_env_percentage("WEB_CAPACITY_LOG_PCT", 20),
            throttle_at_percentage: read_env_percentage("WEB_CAPACITY_THROTTLE_PCT", 70),
            dl_only_at_percentage: read_env_percentage("WEB_CAPACITY_DL_ONLY_PCT", 80),
        }
    }
}

impl AroundMiddleware for BalanceCapacity {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for BalanceCapacity {
    fn call(&self, request: &mut dyn RequestExt) -> AfterResult {
        // The _drop_on_exit ensures the counter is decremented for all exit paths (including panics)
        let (_drop_on_exit, count) = RequestCounter::add_one(&self.in_flight_requests);
        let handler = self.handler.as_ref().unwrap();
        let load = 100 * count / self.capacity;

        // Begin logging request count so early stages of load increase can be located
        if load >= self.log_at_percentage {
            super::log_request::add_custom_metadata(request, "in_flight_requests", count);
        }

        // Download requests are always accepted
        if request.path().starts_with("/api/v1/crates/") && request.path().ends_with("/download") {
            return handler.call(request);
        }

        // Reject read-only requests as load nears capacity. Bots are likely to send only safe
        // requests and this helps prioritize requests that users may be reluctant to retry.
        if load >= self.throttle_at_percentage && request.method().is_safe() {
            return over_capacity_response(request);
        }

        // As load reaches capacity, all non-download requests are rejected
        if load >= self.dl_only_at_percentage {
            return over_capacity_response(request);
        }

        handler.call(request)
    }
}

fn over_capacity_response(request: &mut dyn RequestExt) -> AfterResult {
    // TODO: Generate an alert so we can investigate
    super::log_request::add_custom_metadata(request, "cause", "over capacity");
    let body = "Service temporarily unavailable";
    Response::builder()
        .status(StatusCode::SERVICE_UNAVAILABLE)
        .header(header::CONTENT_LENGTH, body.len())
        .body(Body::from_static(body.as_bytes()))
        .map_err(box_error)
}

fn read_env_percentage(name: &str, default: usize) -> usize {
    if let Ok(value) = std::env::var(name) {
        value.parse().unwrap_or(default)
    } else {
        default
    }
}

// FIXME(JTG): I've copied the following from my `conduit-hyper` crate.  Once we transition from
// `civet`, we could pass the in_flight_request count from `condut-hyper` via a request extension.

/// A struct that stores a reference to an atomic counter so it can be decremented when dropped
struct RequestCounter<'a> {
    counter: &'a AtomicUsize,
}

impl<'a> RequestCounter<'a> {
    fn add_one(counter: &'a AtomicUsize) -> (Self, usize) {
        let previous = counter.fetch_add(1, Ordering::SeqCst);
        (Self { counter }, previous + 1)
    }
}

impl<'a> Drop for RequestCounter<'a> {
    fn drop(&mut self) {
        self.counter.fetch_sub(1, Ordering::SeqCst);
    }
}
<commit_msg>Add a report-only mode to the `BalanceCapacity` middleware<commit_after>//! Reject certain requests as instance load reaches capacity.
//!
//! The primary goal of this middleware is to avoid starving the download endpoint of resources.
//! When bots send many parallel requests that run slow database queries, download requests may
//! block and eventually timeout waiting for a database connection.
//!
//! Bots must continue to respect our crawler policy, but until we can manually block bad clients
//! we should avoid dropping download requests even if that means rejecting some legitimate
//! requests to other endpoints.

use std::env;
use std::sync::atomic::{AtomicUsize, Ordering};

use super::prelude::*;
use conduit::{RequestExt, StatusCode};

#[derive(Default)]
pub(super) struct BalanceCapacity {
    handler: Option<Box<dyn Handler>>,
    capacity: usize,
    in_flight_requests: AtomicUsize,
    report_only: bool,
    log_at_percentage: usize,
    throttle_at_percentage: usize,
    dl_only_at_percentage: usize,
}

impl BalanceCapacity {
    pub fn new(capacity: usize) -> Self {
        Self {
            handler: None,
            capacity,
            in_flight_requests: AtomicUsize::new(0),
            report_only: env::var("WEB_CAPACITY_REPORT_ONLY").ok().is_some(),
            log_at_percentage: read_env_percentage("WEB_CAPACITY_LOG_PCT", 50),
            throttle_at_percentage: read_env_percentage("WEB_CAPACITY_THROTTLE_PCT", 70),
            dl_only_at_percentage: read_env_percentage("WEB_CAPACITY_DL_ONLY_PCT", 80),
        }
    }
}

impl AroundMiddleware for BalanceCapacity {
    fn with_handler(&mut self, handler: Box<dyn Handler>) {
        self.handler = Some(handler);
    }
}

impl Handler for BalanceCapacity {
    fn call(&self, request: &mut dyn RequestExt) -> AfterResult {
        // The _drop_on_exit ensures the counter is decremented for all exit paths (including panics)
        let (_drop_on_exit, count) = RequestCounter::add_one(&self.in_flight_requests);
        let handler = self.handler.as_ref().unwrap();
        let load = 100 * count / self.capacity;

        // Begin logging request count so early stages of load increase can be located
        if load >= self.log_at_percentage {
            super::log_request::add_custom_metadata(request, "in_flight_requests", count);
        }

        // In report-only mode we serve all requests and only enforce the logging limit above
        if self.report_only {
            return handler.call(request);
        }

        // Download requests are always accepted
        if request.path().starts_with("/api/v1/crates/") && request.path().ends_with("/download") {
            return handler.call(request);
        }

        // Reject read-only requests as load nears capacity. Bots are likely to send only safe
        // requests and this helps prioritize requests that users may be reluctant to retry.
        if load >= self.throttle_at_percentage && request.method().is_safe() {
            return over_capacity_response(request);
        }

        // As load reaches capacity, all non-download requests are rejected
        if load >= self.dl_only_at_percentage {
            return over_capacity_response(request);
        }

        handler.call(request)
    }
}

fn over_capacity_response(request: &mut dyn RequestExt) -> AfterResult {
    // TODO: Generate an alert so we can investigate
    super::log_request::add_custom_metadata(request, "cause", "over capacity");
    let body = "Service temporarily unavailable";
    Response::builder()
        .status(StatusCode::SERVICE_UNAVAILABLE)
        .header(header::CONTENT_LENGTH, body.len())
        .body(Body::from_static(body.as_bytes()))
        .map_err(box_error)
}

fn read_env_percentage(name: &str, default: usize) -> usize {
    if let Ok(value) = env::var(name) {
        value.parse().unwrap_or(default)
    } else {
        default
    }
}

// FIXME(JTG): I've copied the following from my `conduit-hyper` crate.  Once we transition from
// `civet`, we could pass the in_flight_request count from `condut-hyper` via a request extension.

/// A struct that stores a reference to an atomic counter so it can be decremented when dropped
struct RequestCounter<'a> {
    counter: &'a AtomicUsize,
}

impl<'a> RequestCounter<'a> {
    fn add_one(counter: &'a AtomicUsize) -> (Self, usize) {
        let previous = counter.fetch_add(1, Ordering::SeqCst);
        (Self { counter }, previous + 1)
    }
}

impl<'a> Drop for RequestCounter<'a> {
    fn drop(&mut self) {
        self.counter.fetch_sub(1, Ordering::SeqCst);
    }
}
<|endoftext|>


<commit_before>use basetypes::*;
use chess_move::MoveStack;
use tt::*;
use position::{Position, Value};

pub fn search(tt: &TranspositionTable,
              p: &mut Position,
              moves: &mut MoveStack,
              nc: &mut NodeCount,
              report_nc: &Fn(NodeCount) -> bool,
              mut alpha: Value, // lower bound
              beta: Value, // upper bound
              depth: usize)
              -> Value {
    if depth == 0 {
        let (value, nodes) = p.evaluate_quiescence(alpha, beta);
        *nc += nodes;
        value
    } else {
        moves.save();
        p.generate_moves(moves);
        let mut no_moves_yet = true;
        while let Some(m) = moves.remove_best_move() {
            if p.do_move(m) {
                let value = if no_moves_yet {
                    -search(tt, p, moves, nc, report_nc, -beta, -alpha, depth - 1)
                } else {
                    match -search(tt, p, moves, nc, report_nc, -alpha - 1, -alpha, depth - 1) {
                        x if x > alpha => {
                            -search(tt, p, moves, nc, report_nc, -beta, -alpha, depth - 1)
                        }
                        x => x,
                    }
                };
                p.undo_move();
                *nc += 1;
                no_moves_yet = false;
                if value >= beta {
                    alpha = value;
                    break;
                }
                if value > alpha {
                    alpha = value;
                }
            }
        }
        moves.restore();
        if no_moves_yet {
            p.evaluate_final()
        } else {
            alpha
        }
    }
}
<commit_msg>refactoring<commit_after>use basetypes::*;
use chess_move::MoveStack;
use tt::*;
use position::{Position, Value};

/// Represents a terminated search condition.
pub struct TerminatedSearch;

pub fn search(tt: &TranspositionTable,
              p: &mut Position,
              moves: &mut MoveStack,
              nc: &mut NodeCount,
              report: &Fn(NodeCount) -> Result<(), TerminatedSearch>,
              mut alpha: Value, // lower bound
              beta: Value, // upper bound
              depth: usize)
              -> Result<Value, TerminatedSearch> {
    assert!(alpha <= beta);
    if depth == 0 {
        // On leaf nodes, do quiescence search.
        let (value, nodes) = p.evaluate_quiescence(alpha, beta);
        *nc += nodes;
        Ok(value)
    } else {
        moves.save();
        p.generate_moves(moves);
        let mut no_moves_yet = true;
        while let Some(m) = moves.remove_best_move() {
            if p.do_move(m) {
                // From time to time, we report how many nodes had
                // been searched since the last report. This also
                // gives an opportunity for the search to be
                // terminated.
                *nc += 1;
                if *nc > NODE_COUNT_REPORT_INTERVAL {
                    try!(report(*nc));
                    *nc = 0;
                }

                let value = if no_moves_yet {
                    // The first move we analyze with a fully open
                    // window (alpha, beta).
                    -try!(search(tt, p, moves, nc, report, -beta, -alpha, depth - 1))
                } else {
                    // For the next moves we first try to prove that
                    // they are not better than our current
                    // favorite. For this purpose we analyze them with
                    // a null window (alpha, alpha + 1). This is
                    // faster than a full window search. Only when we
                    // are certain that the move is better than our
                    // current favorite, we do a full-window search.
                    match -try!(search(tt, p, moves, nc, report, -alpha - 1, -alpha, depth - 1)) {
                        x if x <= alpha => x,
                        _ => -try!(search(tt, p, moves, nc, report, -beta, -alpha, depth - 1)),
                    }
                };
                no_moves_yet = false;
                p.undo_move();

                if value >= beta {
                    // This move is too good, so that the opponent
                    // will not allow this line of play to
                    // happen. Therefore we can stop here.
                    alpha = value;
                    break;
                }
                if value > alpha {
                    // We found ourselves a new favorite.
                    alpha = value;
                }
            }
        }
        moves.restore();
        if no_moves_yet {
            // This is a final position.
            Ok(p.evaluate_final())
        } else {
            Ok(alpha)
        }
    }
}

const NODE_COUNT_REPORT_INTERVAL: NodeCount = 10000;
<|endoftext|>