<commit_before>#![recursion_limit = "256"]
// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2
#![allow(non_snake_case)]

// mod api;
// mod cors;
// mod files;

extern crate actix;
extern crate actix_web;
extern crate env_logger;

extern crate postgres;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

extern crate dotenv;
use dotenv::dotenv;
use std::env;

use actix_web::{http::Method, middleware, server, App, FromRequest, HttpRequest, HttpResponse};

extern crate futures;
use futures::future::{result, FutureResult};

extern crate typed_html;
extern crate typed_html_macros;

use typed_html::elements::FlowContent;
use typed_html::types::Metadata;
use typed_html::{dom::DOMTree, html, text, OutputType};

#[derive(Serialize, Debug)]
struct TemplateContext {
    parent: String,
    name: String,
    content: String,
    items: Vec<String>,
}

fn index(_req: &HttpRequest) -> &'static str {
    "Hello world"
}

use std::path;
use std::process::Command;

#[derive(Deserialize)]
struct TemplateParams {
    ssr: bool,
}

fn template(req: &HttpRequest) -> FutureResult<HttpResponse, actix_web::error::Error> {
    let params = actix_web::Path::<TemplateParams>::extract(req).unwrap();
    let ssr = params.ssr;
    let s2 = getStr();
    let s: String = if ssr { s2.to_owned() } else { "".to_owned() };
    let context = TemplateContext {
        parent: "index".to_owned(),
        name: "Roman".to_owned(),
        content: s.to_owned(),
        items: vec!["One", "Two", "Three"]
            .iter()
            .map(|s| s.to_string())
            .collect(),
    };

    let doc: DOMTree<String> = doc(
        html!(

"Hello Kitty"

                    "She is not a cat. She is a human girl."

                { (0..3).map(|_| html!(

                        "Her name is Kitty White."

                )) }

                    "We still don't know how she eats."

"Hello Kitty"

        ),
        context,
    );
    let doc_str = "<!doctype html>".to_owned() + &doc.to_string();

    result(Ok(HttpResponse::Ok()
        .content_type("text/html")
        .body(doc_str)))
}

fn doc<T: OutputType + 'static>(
    tree: Box<dyn FlowContent<T>>,
    context: TemplateContext,
) -> DOMTree<T> {
    let TemplateContext { name, items, .. } = context;
    html!(

                <title>"Hello Kitty"</title>
                <meta charset="utf-8" />
                <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                <link rel="icon" href="/favicon.ico?v=1" />
                <link href="/styles/normalize.css" rel="stylesheet" type="text/css" media="all" />
                <link href="/styles/style.css" rel="stylesheet" type="text/css" media="all" />
                <base href="/"></base>
                <meta name=Metadata::Author content="Not Sanrio Co., Ltd" />

{text!("{}", name)}

"Here are your items:"

                   {
                    items.iter().map(|item| html!(

{text!("{}", item)}

                    ))
                   }

                { tree }

"Try going to ""/hello/YourName"

    )
}

use std::fs;
use std::fs::OpenOptions;
use std::io::prelude::*;
extern crate time;

fn getStr() -> String {
    fs::copy(
        "../client/src/elm/Main.elm",
        "../client/src/elm/Main.elm.bak",
    )
    .expect("file not copied");
    let stdout: Vec<u8>;
    {
        let mut main_file = OpenOptions::new()
            .append(true)
            .open("../client/src/elm/Main.elm")
            .expect("file not opened");

        let str1 = format!(
            r#"
view : Html Msg
view =
    viewWithModel <|
        Model [] HomeRoute <|
            Flags "" {time} ""
"#,
            time = time::get_time().sec
        );

        main_file
            .write(str1.as_bytes())
            .expect("file content not saved");

        stdout = Command::new("node")
            .current_dir(&path::Path::new("../client"))
            .arg("./node_modules/elm-static-html/index.js")
            .arg("-f")
            .arg("src/elm/Main.elm")
            .output()
            .expect("elm-static-html command failed to start")
            .stdout;
    }
    fs::rename(
        "../client/src/elm/Main.elm.bak",
        "../client/src/elm/Main.elm",
    )
    .expect("file not renamed");

    String::from_utf8_lossy(&*stdout)
        .lines()
        .skip_while(|x| x.find("id=\"content\"").is_none())
        .collect()
}

// #[error(404)]
// fn not_found(req: &Request) -> CORS<Template> {
//     let mut map = std::collections::HashMap::new();
//     map.insert("path", req.uri().as_str());
//     CORS::any(Template::render("error/404", &map))
// }

fn main() {
    dotenv().ok();
    env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    let sys = actix::System::new("hello-world");

    server::new(|| {
        App::new()
            .middleware(middleware::Logger::default())
            .resource("/", |r| r.f(index))
            .resource("/template/{ssr}", |r| r.method(Method::GET).a(template))
    })
    .bind("127.0.0.1:8080")
    .unwrap()
    .start();

    println!("Starting http server: 127.0.0.1:8080");

    let _ = sys.run();

    // println!("{:?}", env::var("data_server").unwrap());
    // rocket::ignite()
    //     .mount(
    //         "/",
    //         routes![
    //             template,
    //             files::favicon,
    //             files::index,
    //             files::redirect_to_index,
    //             files::js,
    //             files::styles,
    //             files::styles_with_query,
    //             files::images
    //         ],
    //     )
    //     .mount(
    //         "/api",
    //         routes![
    //             api::user_information,
    //             api::data_sets,
    //             api::data_set,
    //             api::data_set_category,
    //             api::data_sets_categories,
    //             api::data_sets_new
    //         ],
    //     )
    //     .catch(errors![not_found])
    //     .launch();
}
<commit_msg>elm generated content displayed with DYNAMIC_CONTENT<commit_after>#![recursion_limit = "256"]
// http://stackoverflow.com/questions/25877285/how-to-disable-unused-code-warnings-in-rust
// https://users.rust-lang.org/t/turning-off-compiler-warning-messages/4975/2
#![allow(non_snake_case)]

// mod api;
// mod cors;
// mod files;

extern crate actix;
extern crate actix_web;
extern crate env_logger;

extern crate postgres;
extern crate serde_json;
#[macro_use]
extern crate serde_derive;

extern crate dotenv;
use dotenv::dotenv;
use std::env;

use actix_web::{http::Method, middleware, server, App, FromRequest, HttpRequest, HttpResponse};

extern crate futures;
use futures::future::{result, FutureResult};

extern crate typed_html;
extern crate typed_html_macros;

use typed_html::elements::FlowContent;
use typed_html::types::Metadata;
use typed_html::{dom::DOMTree, html, text, OutputType};

#[derive(Serialize, Debug)]
struct TemplateContext {
    parent: String,
    name: String,
    content: String,
    items: Vec<String>,
}

fn index(_req: &HttpRequest) -> &'static str {
    "Hello world"
}

use std::path;
use std::process::Command;

#[derive(Deserialize)]
struct TemplateParams {
    ssr: bool,
}

fn template(req: &HttpRequest) -> FutureResult<HttpResponse, actix_web::error::Error> {
    let params = actix_web::Path::<TemplateParams>::extract(req).unwrap();
    let ssr = params.ssr;
    let s2 = getStr();
    let s: String = if ssr { s2.to_owned() } else { "".to_owned() };
    let context = TemplateContext {
        parent: "index".to_owned(),
        name: "Roman".to_owned(),
        content: s.to_owned(),
        items: vec!["One", "Two", "Three"]
            .iter()
            .map(|s| s.to_string())
            .collect(),
    };

    let doc: DOMTree<String> = doc(
        html!(

"Hello Kitty"

                    "She is not a cat. She is a human girl."

                { (0..3).map(|_| html!(

                        "Her name is Kitty White."

                )) }

                    "We still don't know how she eats."

"Hello Kitty"

                "DYNAMIC_CONTENT"

        ),
        context,
    );
    let mut doc_str = "<!doctype html>".to_owned() + &doc.to_string();

    // https://users.rust-lang.org/t/how-to-create-a-macro-from-dynamic-content/5079
    doc_str = doc_str.replacen("DYNAMIC_CONTENT", &s2, 1);

    result(Ok(HttpResponse::Ok()
        .content_type("text/html")
        .body(doc_str)))
}

fn doc<T: OutputType + 'static>(
    tree: Box<dyn FlowContent<T>>,
    context: TemplateContext,
) -> DOMTree<T> {
    let TemplateContext { name, items, .. } = context;
    html!(

                <title>"Hello Kitty"</title>
                <meta charset="utf-8" />
                <meta name="viewport" content="width=device-width, initial-scale=1.0" />
                <link rel="icon" href="/favicon.ico?v=1" />
                <link href="/styles/normalize.css" rel="stylesheet" type="text/css" media="all" />
                <link href="/styles/style.css" rel="stylesheet" type="text/css" media="all" />
                <base href="/"></base>
                <meta name=Metadata::Author content="Not Sanrio Co., Ltd" />

{text!("{}", name)}

"Here are your items:"

                   {
                    items.iter().map(|item| html!(

{text!("{}", item)}

                    ))
                   }

                { tree }

"Try going to ""/hello/YourName"

    )
}

use std::fs;
use std::fs::OpenOptions;
use std::io::prelude::*;
extern crate time;

fn getStr() -> String {
    fs::copy(
        "../client/src/elm/Main.elm",
        "../client/src/elm/Main.elm.bak",
    )
    .expect("file not copied");
    let stdout: Vec<u8>;
    {
        let mut main_file = OpenOptions::new()
            .append(true)
            .open("../client/src/elm/Main.elm")
            .expect("file not opened");

        let str1 = format!(
            r#"
view : Html Msg
view =
    viewWithModel <|
        Model [] HomeRoute <|
            Flags "" {time} ""
"#,
            time = time::get_time().sec
        );

        main_file
            .write(str1.as_bytes())
            .expect("file content not saved");

        stdout = Command::new("node")
            .current_dir(&path::Path::new("../client"))
            .arg("./node_modules/elm-static-html/index.js")
            .arg("-f")
            .arg("src/elm/Main.elm")
            .output()
            .expect("elm-static-html command failed to start")
            .stdout;
    }
    fs::rename(
        "../client/src/elm/Main.elm.bak",
        "../client/src/elm/Main.elm",
    )
    .expect("file not renamed");

    String::from_utf8_lossy(&*stdout)
        .lines()
        .skip_while(|x| x.find("id=\"content\"").is_none())
        .collect()
}

// #[error(404)]
// fn not_found(req: &Request) -> CORS<Template> {
//     let mut map = std::collections::HashMap::new();
//     map.insert("path", req.uri().as_str());
//     CORS::any(Template::render("error/404", &map))
// }

fn main() {
    dotenv().ok();
    env::set_var("RUST_LOG", "actix_web=info");
    env_logger::init();
    let sys = actix::System::new("hello-world");

    server::new(|| {
        App::new()
            .middleware(middleware::Logger::default())
            .resource("/", |r| r.f(index))
            .resource("/template/{ssr}", |r| r.method(Method::GET).a(template))
    })
    .bind("127.0.0.1:8080")
    .unwrap()
    .start();

    println!("Starting http server: 127.0.0.1:8080");

    let _ = sys.run();

    // println!("{:?}", env::var("data_server").unwrap());
    // rocket::ignite()
    //     .mount(
    //         "/",
    //         routes![
    //             template,
    //             files::favicon,
    //             files::index,
    //             files::redirect_to_index,
    //             files::js,
    //             files::styles,
    //             files::styles_with_query,
    //             files::images
    //         ],
    //     )
    //     .mount(
    //         "/api",
    //         routes![
    //             api::user_information,
    //             api::data_sets,
    //             api::data_set,
    //             api::data_set_category,
    //             api::data_sets_categories,
    //             api::data_sets_new
    //         ],
    //     )
    //     .catch(errors![not_found])
    //     .launch();
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate criterion;

extern crate gluon_base as base;
extern crate gluon_parser as parser;

use criterion::{Bencher, Criterion};

use crate::base::symbol::{SymbolModule, Symbols};
use crate::base::types::TypeCache;

fn parse_prelude(b: &mut Bencher) {
    use std::fs::File;
    use std::io::Read;
    let mut text = String::new();
    File::open("std/prelude.glu")
        .unwrap()
        .read_to_string(&mut text)
        .unwrap();
    b.iter(|| {
        let mut symbols = Symbols::new();
        let mut symbols = SymbolModule::new("".into(), &mut symbols);
        parser::parse_expr(&mut symbols, &TypeCache::default(), &text)
            .unwrap_or_else(|err| panic!("{:?}", err))
    })
}

fn parse_benchmark(c: &mut Criterion) {
    c.bench_function("std/prelude", parse_prelude);
}

criterion_group!(parser, parse_benchmark);
criterion_main!(parser);
<commit_msg>chore: Add more parser benchmarks<commit_after>#[macro_use]
extern crate criterion;

extern crate gluon_base as base;
extern crate gluon_parser as parser;

use std::fs;

use criterion::{Bencher, Criterion};

use crate::base::{
    symbol::{SymbolModule, Symbols},
    types::TypeCache,
};

fn parse_file(b: &mut Bencher, file: &str) {
    let text = fs::read_to_string(file).unwrap();

    b.iter(|| {
        let mut symbols = Symbols::new();
        let mut symbols = SymbolModule::new("".into(), &mut symbols);
        parser::parse_expr(&mut symbols, &TypeCache::default(), &text)
            .unwrap_or_else(|err| panic!("{:?}", err))
    })
}

fn parse_benchmark(c: &mut Criterion) {
    c.bench_function("std/prelude", |b| parse_file(b, "std/prelude.glu"));
    c.bench_function("examples/lisp", |b| parse_file(b, "examples/lisp/lisp.glu"));
    c.bench_function("examples/http", |b| {
        parse_file(b, "examples/http/server.glu")
    });
}

criterion_group!(parser, parse_benchmark);
criterion_main!(parser);
<|endoftext|>


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

// Extracted from https://github.com/rust-num/num.

// Rust 1.5 is unhappy that this private module is undocumented.
#![allow(missing_docs)]

use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};
use core::mem::size_of;

macro_rules! int_to_int {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            if size_of::<$SrcT>() <= size_of::<$DstT>() {
                Some($slf as $DstT)
            } else {
                let n = $slf as i64;
                if <$DstT>::min_value() as i64 <= n && n <= <$DstT>::max_value() as i64 {
                    Some($slf as $DstT)
                } else {
                    None
                }
            }
        }
    )
}

macro_rules! int_to_uint {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            let zero: $SrcT = 0;
            if zero <= $slf && $slf as u64 <= <$DstT>::max_value() as u64 {
                Some($slf as $DstT)
            } else {
                None
            }
        }
    )
}

macro_rules! uint_to_int {
    ($DstT:ty, $slf:expr) => (
        {
            if $slf as u64 <= <$DstT>::max_value() as u64 {
                Some($slf as $DstT)
            } else {
                None
            }
        }
    )
}

macro_rules! uint_to_uint {
    ($SrcT:ty, $DstT:ty, $slf:expr) => (
        {
            if size_of::<$SrcT>() <= size_of::<$DstT>() {
                Some($slf as $DstT)
            } else {
                let zero: $SrcT = 0;
                if zero <= $slf && $slf as u64 <= <$DstT>::max_value() as u64 {
                    Some($slf as $DstT)
                } else {
                    None
                }
            }
        }
    )
}

pub trait FromPrimitive: Sized {
    fn from_isize(n: isize) -> Option<Self>;
    fn from_i8(n: i8) -> Option<Self>;
    fn from_i16(n: i16) -> Option<Self>;
    fn from_i32(n: i32) -> Option<Self>;
    fn from_i64(n: i64) -> Option<Self>;
    fn from_usize(n: usize) -> Option<Self>;
    fn from_u8(n: u8) -> Option<Self>;
    fn from_u16(n: u16) -> Option<Self>;
    fn from_u32(n: u32) -> Option<Self>;
    fn from_u64(n: u64) -> Option<Self>;
}

macro_rules! impl_from_primitive_for_int {
    ($T:ty) => (
        impl FromPrimitive for $T {
            #[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!(isize, $T, n) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!(i8, $T, n) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!(i16, $T, n) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!(i32, $T, n) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!(i64, $T, n) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { uint_to_int!($T, n) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { uint_to_int!($T, n) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { uint_to_int!($T, n) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { uint_to_int!($T, n) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { uint_to_int!($T, n) }
        }
    )
}

macro_rules! impl_from_primitive_for_uint {
    ($T:ty) => (
        impl FromPrimitive for $T {
            #[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!(isize, $T, n) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!(i8, $T, n) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!(i16, $T, n) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!(i32, $T, n) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!(i64, $T, n) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { uint_to_uint!(usize, $T, n) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { uint_to_uint!(u8, $T, n) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { uint_to_uint!(u16, $T, n) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { uint_to_uint!(u32, $T, n) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { uint_to_uint!(u64, $T, n) }
        }
    )
}

macro_rules! impl_from_primitive_for_float {
    ($T:ty) => (
        impl FromPrimitive for $T {
            #[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
        }
    )
}

impl_from_primitive_for_int!(isize);
impl_from_primitive_for_int!(i8);
impl_from_primitive_for_int!(i16);
impl_from_primitive_for_int!(i32);
impl_from_primitive_for_int!(i64);
impl_from_primitive_for_uint!(usize);
impl_from_primitive_for_uint!(u8);
impl_from_primitive_for_uint!(u16);
impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64);
<commit_msg>Simplify integer conversion logic<commit_after>// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use core::{usize, u8, u16, u32, u64};
use core::{isize, i8, i16, i32, i64};
use core::{f32, f64};

macro_rules! int_to_int {
    ($dst:ident, $n:ident) => (
        if $dst::MIN as i64 <= $n as i64 && $n as i64 <= $dst::MAX as i64 {
            Some($n as $dst)
        } else {
            None
        }
    )
}

macro_rules! int_to_uint {
    ($dst:ident, $n:ident) => (
        if 0 <= $n && $n as u64 <= $dst::MAX as u64 {
            Some($n as $dst)
        } else {
            None
        }
    )
}

macro_rules! uint_to {
    ($dst:ident, $n:ident) => (
        if $n as u64 <= $dst::MAX as u64 {
            Some($n as $dst)
        } else {
            None
        }
    )
}

pub trait FromPrimitive: Sized {
    fn from_isize(n: isize) -> Option<Self>;
    fn from_i8(n: i8) -> Option<Self>;
    fn from_i16(n: i16) -> Option<Self>;
    fn from_i32(n: i32) -> Option<Self>;
    fn from_i64(n: i64) -> Option<Self>;
    fn from_usize(n: usize) -> Option<Self>;
    fn from_u8(n: u8) -> Option<Self>;
    fn from_u16(n: u16) -> Option<Self>;
    fn from_u32(n: u32) -> Option<Self>;
    fn from_u64(n: u64) -> Option<Self>;
}

macro_rules! impl_from_primitive_for_int {
    ($t:ident) => (
        impl FromPrimitive for $t {
            #[inline] fn from_isize(n: isize) -> Option<Self> { int_to_int!($t, n) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { int_to_int!($t, n) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { int_to_int!($t, n) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { int_to_int!($t, n) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { int_to_int!($t, n) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
        }
    )
}

macro_rules! impl_from_primitive_for_uint {
    ($t:ident) => (
        impl FromPrimitive for $t {
            #[inline] fn from_isize(n: isize) -> Option<Self> { int_to_uint!($t, n) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { int_to_uint!($t, n) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { int_to_uint!($t, n) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { int_to_uint!($t, n) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { int_to_uint!($t, n) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { uint_to!($t, n) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { uint_to!($t, n) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { uint_to!($t, n) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { uint_to!($t, n) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { uint_to!($t, n) }
        }
    )
}

macro_rules! impl_from_primitive_for_float {
    ($t:ident) => (
        impl FromPrimitive for $t {
            #[inline] fn from_isize(n: isize) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i8(n: i8) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i16(n: i16) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i32(n: i32) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_i64(n: i64) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_usize(n: usize) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u8(n: u8) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u16(n: u16) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u32(n: u32) -> Option<Self> { Some(n as Self) }
            #[inline] fn from_u64(n: u64) -> Option<Self> { Some(n as Self) }
        }
    )
}

impl_from_primitive_for_int!(isize);
impl_from_primitive_for_int!(i8);
impl_from_primitive_for_int!(i16);
impl_from_primitive_for_int!(i32);
impl_from_primitive_for_int!(i64);
impl_from_primitive_for_uint!(usize);
impl_from_primitive_for_uint!(u8);
impl_from_primitive_for_uint!(u16);
impl_from_primitive_for_uint!(u32);
impl_from_primitive_for_uint!(u64);
impl_from_primitive_for_float!(f32);
impl_from_primitive_for_float!(f64);
<|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/. */

/// Liberally derived from the [Firefox JS implementation](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webbrowser.js).
/// Connection point for remote devtools that wish to investigate a particular tab's contents.
/// Supports dynamic attaching and detaching which control notifications of navigation, etc.

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use devtools_traits::WantsLiveNotifications;
use protocol::JsonPacketStream;

use serialize::json;
use std::io::TcpStream;

#[derive(RustcEncodable)]
struct TabTraits;

#[derive(RustcEncodable)]
struct TabAttachedReply {
    from: String,
    __type__: String,
    threadActor: String,
    cacheDisabled: bool,
    javascriptEnabled: bool,
    traits: TabTraits,
}

#[derive(RustcEncodable)]
struct TabDetachedReply {
    from: String,
    __type__: String,
}

#[derive(RustcEncodable)]
struct ReconfigureReply {
    from: String
}

#[derive(RustcEncodable)]
struct ListFramesReply {
    from: String,
    frames: Vec<FrameMsg>,
}

#[derive(RustcEncodable)]
struct FrameMsg {
    id: uint,
    url: String,
    title: String,
    parentID: uint,
}

#[derive(RustcEncodable)]
pub struct TabActorMsg {
    actor: String,
    title: String,
    url: String,
    outerWindowID: uint,
    consoleActor: String,
    inspectorActor: String,
}

pub struct TabActor {
    pub name: String,
    pub title: String,
    pub url: String,
    pub console: String,
    pub inspector: String,
}

impl Actor for TabActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      registry: &ActorRegistry,
                      msg_type: &String,
                      _msg: &json::Object,
                      stream: &mut TcpStream) -> Result<bool, ()> {
        Ok(match msg_type.as_slice() {
            "reconfigure" => {
                stream.write_json_packet(&ReconfigureReply { from: self.name() });
                true
            }

            // https://wiki.mozilla.org/Remote_Debugging_Protocol#Listing_Browser_Tabs
            // (see "To attach to a _tabActor_")
            "attach" => {
                let msg = TabAttachedReply {
                    from: self.name(),
                    __type__: "tabAttached".to_string(),
                    threadActor: self.name(),
                    cacheDisabled: false,
                    javascriptEnabled: true,
                    traits: TabTraits,
                };
                let console_actor = registry.find::<ConsoleActor>(self.console.as_slice());
                console_actor.streams.borrow_mut().push(stream.clone());
                stream.write_json_packet(&msg);
                console_actor.script_chan.send(WantsLiveNotifications(console_actor.pipeline, true));
                true
            }

            //FIXME: The current implementation won't work for multiple connections. Need to ensure 105
            //       that the correct stream is removed.
            "detach" => {
                let msg = TabDetachedReply {
                    from: self.name(),
                    __type__: "detached".to_string(),
                };
                let console_actor = registry.find::<ConsoleActor>(self.console.as_slice());
                console_actor.streams.borrow_mut().pop();
                stream.write_json_packet(&msg);
                console_actor.script_chan.send(WantsLiveNotifications(console_actor.pipeline, false));
                true
            }

            "listFrames" => {
                let msg = ListFramesReply {
                    from: self.name(),
                    frames: vec!(),
                };
                stream.write_json_packet(&msg);
                true
            }

            _ => false
        })
    }
}

impl TabActor {
    pub fn encodable(&self) -> TabActorMsg {
        TabActorMsg {
            actor: self.name(),
            title: self.title.clone(),
            url: self.url.clone(),
            outerWindowID: 0, //FIXME: this should probably be the pipeline id
            consoleActor: self.console.clone(),
            inspectorActor: self.inspector.clone(),
        }
    }
}
<commit_msg>auto merge of #4860 : Ms2ger/servo/warnings-4852, r=jdm<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/. */

/// Liberally derived from the [Firefox JS implementation](http://mxr.mozilla.org/mozilla-central/source/toolkit/devtools/server/actors/webbrowser.js).
/// Connection point for remote devtools that wish to investigate a particular tab's contents.
/// Supports dynamic attaching and detaching which control notifications of navigation, etc.

use actor::{Actor, ActorRegistry};
use actors::console::ConsoleActor;
use devtools_traits::WantsLiveNotifications;
use protocol::JsonPacketStream;

use serialize::json;
use std::io::TcpStream;

#[derive(RustcEncodable)]
struct TabTraits;

#[derive(RustcEncodable)]
struct TabAttachedReply {
    from: String,
    __type__: String,
    threadActor: String,
    cacheDisabled: bool,
    javascriptEnabled: bool,
    traits: TabTraits,
}

#[derive(RustcEncodable)]
struct TabDetachedReply {
    from: String,
    __type__: String,
}

#[derive(RustcEncodable)]
struct ReconfigureReply {
    from: String
}

#[derive(RustcEncodable)]
struct ListFramesReply {
    from: String,
    frames: Vec<FrameMsg>,
}

#[derive(RustcEncodable)]
struct FrameMsg {
    id: uint,
    url: String,
    title: String,
    parentID: uint,
}

#[derive(RustcEncodable)]
pub struct TabActorMsg {
    actor: String,
    title: String,
    url: String,
    outerWindowID: uint,
    consoleActor: String,
    inspectorActor: String,
}

pub struct TabActor {
    pub name: String,
    pub title: String,
    pub url: String,
    pub console: String,
    pub inspector: String,
}

impl Actor for TabActor {
    fn name(&self) -> String {
        self.name.clone()
    }

    fn handle_message(&self,
                      registry: &ActorRegistry,
                      msg_type: &String,
                      _msg: &json::Object,
                      stream: &mut TcpStream) -> Result<bool, ()> {
        Ok(match msg_type.as_slice() {
            "reconfigure" => {
                stream.write_json_packet(&ReconfigureReply { from: self.name() });
                true
            }

            // https://wiki.mozilla.org/Remote_Debugging_Protocol#Listing_Browser_Tabs
            // (see "To attach to a _tabActor_")
            "attach" => {
                let msg = TabAttachedReply {
                    from: self.name(),
                    __type__: "tabAttached".to_string(),
                    threadActor: self.name(),
                    cacheDisabled: false,
                    javascriptEnabled: true,
                    traits: TabTraits,
                };
                let console_actor = registry.find::<ConsoleActor>(self.console.as_slice());
                console_actor.streams.borrow_mut().push(stream.clone());
                stream.write_json_packet(&msg);
                console_actor.script_chan.send(WantsLiveNotifications(console_actor.pipeline, true)).unwrap();
                true
            }

            //FIXME: The current implementation won't work for multiple connections. Need to ensure 105
            //       that the correct stream is removed.
            "detach" => {
                let msg = TabDetachedReply {
                    from: self.name(),
                    __type__: "detached".to_string(),
                };
                let console_actor = registry.find::<ConsoleActor>(self.console.as_slice());
                console_actor.streams.borrow_mut().pop();
                stream.write_json_packet(&msg);
                console_actor.script_chan.send(WantsLiveNotifications(console_actor.pipeline, false)).unwrap();
                true
            }

            "listFrames" => {
                let msg = ListFramesReply {
                    from: self.name(),
                    frames: vec!(),
                };
                stream.write_json_packet(&msg);
                true
            }

            _ => false
        })
    }
}

impl TabActor {
    pub fn encodable(&self) -> TabActorMsg {
        TabActorMsg {
            actor: self.name(),
            title: self.title.clone(),
            url: self.url.clone(),
            outerWindowID: 0, //FIXME: this should probably be the pipeline id
            consoleActor: self.console.clone(),
            inspectorActor: self.inspector.clone(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    data_stream::{DataStream, DataStreamId, DataStreamListener},
    error::Error,
    logging::{LogEntry, LogEvent, LogSchema},
    metrics,
    metrics::increment_counter,
    streaming_client::{
        StreamRequest, StreamRequestMessage, StreamingServiceListener, TerminateStreamRequest,
    },
};
use aptos_config::config::DataStreamingServiceConfig;
use aptos_data_client::{AptosDataClient, GlobalDataSummary, OptimalChunkSizes};
use aptos_id_generator::{IdGenerator, U64IdGenerator};
use aptos_logger::prelude::*;
use futures::StreamExt;
use std::{collections::HashMap, sync::Arc, time::Duration};
use tokio::time::interval;
use tokio_stream::wrappers::IntervalStream;

// Useful constants for the Data Streaming Service
const GLOBAL_DATA_REFRESH_LOG_FREQ_SECS: u64 = 1;

/// The data streaming service that responds to data stream requests.
pub struct DataStreamingService<T> {
    // The configuration for this streaming service.
    config: DataStreamingServiceConfig,

    // The data client through which to fetch data from the Aptos network
    aptos_data_client: T,

    // Cached global data summary
    global_data_summary: GlobalDataSummary,

    // All requested data streams from clients
    data_streams: HashMap<DataStreamId, DataStream<T>>,

    // The listener through which to hear new client stream requests
    stream_requests: StreamingServiceListener,

    // Unique ID generators to maintain unique IDs across streams
    stream_id_generator: U64IdGenerator,
    notification_id_generator: Arc<U64IdGenerator>,
}

impl<T: AptosDataClient + Send + Clone + 'static> DataStreamingService<T> {
    pub fn new(
        config: DataStreamingServiceConfig,
        aptos_data_client: T,
        stream_requests: StreamingServiceListener,
    ) -> Self {
        Self {
            config,
            aptos_data_client,
            global_data_summary: GlobalDataSummary::empty(),
            data_streams: HashMap::new(),
            stream_requests,
            stream_id_generator: U64IdGenerator::new(),
            notification_id_generator: Arc::new(U64IdGenerator::new()),
        }
    }

    /// Starts the dedicated streaming service
    pub async fn start_service(mut self) {
        let mut data_refresh_interval = IntervalStream::new(interval(Duration::from_millis(
            self.config.global_summary_refresh_interval_ms,
        )))
        .fuse();
        let mut progress_check_interval = IntervalStream::new(interval(Duration::from_millis(
            self.config.progress_check_interval_ms,
        )))
        .fuse();

        loop {
            ::futures::select! {
                stream_request = self.stream_requests.select_next_some() => {
                    self.handle_stream_request_message(stream_request);
                }
                _ = data_refresh_interval.select_next_some() => {
                    self.refresh_global_data_summary();
                }
                _ = progress_check_interval.select_next_some() => {
                    self.check_progress_of_all_data_streams();
                }
            }
        }
    }

    /// Handles new stream request messages from clients
    fn handle_stream_request_message(&mut self, request_message: StreamRequestMessage) {
        if let StreamRequest::TerminateStream(request) = request_message.stream_request {
            // Process the feedback request
            if let Err(error) = self.process_terminate_stream_request(&request) {
                error!(LogSchema::new(LogEntry::HandleTerminateRequest)
                    .event(LogEvent::Error)
                    .error(&error));
            }
            return;
        }

        // Process the stream request
        let response = self.process_new_stream_request(&request_message);
        if let Err(error) = &response {
            error!(LogSchema::new(LogEntry::HandleStreamRequest)
                .event(LogEvent::Error)
                .error(error));
        }

        // Send the response to the client
        if let Err(error) = request_message.response_sender.send(response) {
            error!(LogSchema::new(LogEntry::RespondToStreamRequest)
                .event(LogEvent::Error)
                .message(&format!(
                    "Failed to send response for stream request: {:?}",
                    error
                )));
        }
    }

    /// Processes a request for terminating the stream that sent a specific
    /// notification ID.
    fn process_terminate_stream_request(
        &mut self,
        terminate_request: &TerminateStreamRequest,
    ) -> Result<(), Error> {
        // Increment the stream termination counter
        let notification_feedback = &terminate_request.notification_feedback;
        increment_counter(
            &metrics::TERMINATE_DATA_STREAM,
            notification_feedback.get_label().into(),
        );

        // Find the data stream that sent the notification
        let notification_id = &terminate_request.notification_id;
        let data_stream_ids = self.get_all_data_stream_ids();
        for data_stream_id in &data_stream_ids {
            let data_stream = self.get_data_stream(data_stream_id);
            if data_stream.sent_notification(notification_id) {
                info!(LogSchema::new(LogEntry::HandleTerminateRequest)
                    .stream_id(*data_stream_id)
                    .event(LogEvent::Success)
                    .message(&format!(
                        "Terminating the stream that sent notification ID: {:?}. Feedback: {:?}",
                        notification_id, notification_feedback,
                    )));
                data_stream.handle_notification_feedback(notification_id, notification_feedback)?;
                self.data_streams.remove(notification_id);
                return Ok(());
            }
        }

        panic!(
            "Unable to find the stream that sent notification ID: {:?}. Feedback: {:?}",
            notification_id, notification_feedback,
        );
    }

    /// Creates a new stream and ensures the data for that stream is available
    fn process_new_stream_request(
        &mut self,
        request_message: &StreamRequestMessage,
    ) -> Result<DataStreamListener, Error> {
        // Increment the stream creation counter
        increment_counter(
            &metrics::CREATE_DATA_STREAM,
            request_message.stream_request.get_label().into(),
        );

        // Refresh the cached global data summary
        self.refresh_global_data_summary();

        // Create a new data stream
        let stream_id = self.stream_id_generator.next();
        let (data_stream, stream_listener) = DataStream::new(
            self.config,
            stream_id,
            &request_message.stream_request,
            self.aptos_data_client.clone(),
            self.notification_id_generator.clone(),
            &self.global_data_summary.advertised_data,
        )?;

        // Verify the data stream can be fulfilled using the currently advertised data
        data_stream.ensure_data_is_available(&self.global_data_summary.advertised_data)?;

        // Store the data stream internally
        if self.data_streams.insert(stream_id, data_stream).is_some() {
            panic!(
                "Duplicate data stream found! This should not occur! ID: {:?}",
                stream_id,
            );
        }
        info!(LogSchema::new(LogEntry::HandleStreamRequest)
            .stream_id(stream_id)
            .event(LogEvent::Success)
            .message(&format!(
                "Stream created for request: {:?}",
                request_message
            )));

        // Return the listener
        Ok(stream_listener)
    }

    /// Refreshes the global data summary by communicating with the Aptos data client
    fn refresh_global_data_summary(&mut self) {
        if let Err(error) = self.fetch_global_data_summary() {
            increment_counter(
                &metrics::GLOBAL_DATA_SUMMARY_ERROR,
                error.get_label().into(),
            );
            sample!(
                SampleRate::Duration(Duration::from_secs(GLOBAL_DATA_REFRESH_LOG_FREQ_SECS)),
                error!(LogSchema::new(LogEntry::RefreshGlobalData)
                    .event(LogEvent::Error)
                    .error(&error))
            );
        }
    }

    fn fetch_global_data_summary(&mut self) -> Result<(), Error> {
        let global_data_summary = self.aptos_data_client.get_global_data_summary();
        if global_data_summary.is_empty() {
            sample!(
                SampleRate::Duration(Duration::from_secs(GLOBAL_DATA_REFRESH_LOG_FREQ_SECS)),
                info!(LogSchema::new(LogEntry::RefreshGlobalData)
                    .message("Latest global data summary is empty."))
            );
        } else {
            verify_optimal_chunk_sizes(&global_data_summary.optimal_chunk_sizes)?;
            self.global_data_summary = global_data_summary;
        }

        Ok(())
    }

    /// Ensures that all existing data streams are making progress
    fn check_progress_of_all_data_streams(&mut self) {
        let data_stream_ids = self.get_all_data_stream_ids();
        for data_stream_id in &data_stream_ids {
            if let Err(error) = self.update_progress_of_data_stream(data_stream_id) {
                increment_counter(
                    &metrics::CHECK_STREAM_PROGRESS_ERROR,
                    error.get_label().into(),
                );
                error!(LogSchema::new(LogEntry::CheckStreamProgress)
                    .stream_id(*data_stream_id)
                    .event(LogEvent::Error)
                    .error(&error));
            }
        }
    }

    /// Ensures that a data stream has in-flight data requests and handles
    /// any new responses that have arrived since we last checked.
    fn update_progress_of_data_stream(
        &mut self,
        data_stream_id: &DataStreamId,
    ) -> Result<(), Error> {
        let global_data_summary = self.global_data_summary.clone();

        let data_stream = self.get_data_stream_mut(data_stream_id);
        if !data_stream.data_requests_initialized() {
            // Initialize the request batch by sending out data client requests
            data_stream.initialize_data_requests(global_data_summary)?;
            info!(
                (LogSchema::new(LogEntry::InitializeStream)
                    .stream_id(*data_stream_id)
                    .event(LogEvent::Success)
                    .message("Data stream initialized."))
            );
        } else {
            // Process any data client requests that have received responses
            data_stream.process_data_responses(global_data_summary)?;
        }

        Ok(())
    }

    fn get_all_data_stream_ids(&self) -> Vec<DataStreamId> {
        self.data_streams
            .keys()
            .cloned()
            .collect::<Vec<DataStreamId>>()
    }

    /// Returns the data stream associated with the given `data_stream_id`.
    /// Note: this method assumes the caller has already verified the stream exists.
    fn get_data_stream(&self, data_stream_id: &DataStreamId) -> &DataStream<T> {
        self.data_streams.get(data_stream_id).unwrap_or_else(|| {
            panic!(
                "Expected a data stream with ID: {:?}, but found None!",
                data_stream_id
            )
        })
    }

    /// Returns the data stream associated with the given `data_stream_id`.
    /// Note: this method assumes the caller has already verified the stream exists.
    fn get_data_stream_mut(&mut self, data_stream_id: &DataStreamId) -> &mut DataStream<T> {
        self.data_streams
            .get_mut(data_stream_id)
            .unwrap_or_else(|| {
                panic!(
                    "Expected a data stream with ID: {:?}, but found None!",
                    data_stream_id
                )
            })
    }
}

/// Verifies that all optimal chunk sizes are valid (i.e., not zero). Returns an
/// error if a chunk size is 0.
fn verify_optimal_chunk_sizes(optimal_chunk_sizes: &OptimalChunkSizes) -> Result<(), Error> {
    if optimal_chunk_sizes.account_states_chunk_size == 0
        || optimal_chunk_sizes.epoch_chunk_size == 0
        || optimal_chunk_sizes.transaction_chunk_size == 0
        || optimal_chunk_sizes.transaction_output_chunk_size == 0
    {
        Err(Error::AptosDataClientResponseIsInvalid(format!(
            "Found at least one optimal chunk size of zero: {:?}",
            optimal_chunk_sizes
        )))
    } else {
        Ok(())
    }
}
<commit_msg>[State Sync] Avoid logging an error when there's no data to fetch.<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

use crate::{
    data_stream::{DataStream, DataStreamId, DataStreamListener},
    error::Error,
    logging::{LogEntry, LogEvent, LogSchema},
    metrics,
    metrics::increment_counter,
    streaming_client::{
        StreamRequest, StreamRequestMessage, StreamingServiceListener, TerminateStreamRequest,
    },
};
use aptos_config::config::DataStreamingServiceConfig;
use aptos_data_client::{AptosDataClient, GlobalDataSummary, OptimalChunkSizes};
use aptos_id_generator::{IdGenerator, U64IdGenerator};
use aptos_logger::prelude::*;
use futures::StreamExt;
use std::{collections::HashMap, sync::Arc, time::Duration};
use tokio::time::interval;
use tokio_stream::wrappers::IntervalStream;

// Useful constants for the Data Streaming Service
const GLOBAL_DATA_REFRESH_LOG_FREQ_SECS: u64 = 1;
const NO_DATA_TO_FETCH_LOG_FREQ_SECS: u64 = 5;

/// The data streaming service that responds to data stream requests.
pub struct DataStreamingService<T> {
    // The configuration for this streaming service.
    config: DataStreamingServiceConfig,

    // The data client through which to fetch data from the Aptos network
    aptos_data_client: T,

    // Cached global data summary
    global_data_summary: GlobalDataSummary,

    // All requested data streams from clients
    data_streams: HashMap<DataStreamId, DataStream<T>>,

    // The listener through which to hear new client stream requests
    stream_requests: StreamingServiceListener,

    // Unique ID generators to maintain unique IDs across streams
    stream_id_generator: U64IdGenerator,
    notification_id_generator: Arc<U64IdGenerator>,
}

impl<T: AptosDataClient + Send + Clone + 'static> DataStreamingService<T> {
    pub fn new(
        config: DataStreamingServiceConfig,
        aptos_data_client: T,
        stream_requests: StreamingServiceListener,
    ) -> Self {
        Self {
            config,
            aptos_data_client,
            global_data_summary: GlobalDataSummary::empty(),
            data_streams: HashMap::new(),
            stream_requests,
            stream_id_generator: U64IdGenerator::new(),
            notification_id_generator: Arc::new(U64IdGenerator::new()),
        }
    }

    /// Starts the dedicated streaming service
    pub async fn start_service(mut self) {
        let mut data_refresh_interval = IntervalStream::new(interval(Duration::from_millis(
            self.config.global_summary_refresh_interval_ms,
        )))
        .fuse();
        let mut progress_check_interval = IntervalStream::new(interval(Duration::from_millis(
            self.config.progress_check_interval_ms,
        )))
        .fuse();

        loop {
            ::futures::select! {
                stream_request = self.stream_requests.select_next_some() => {
                    self.handle_stream_request_message(stream_request);
                }
                _ = data_refresh_interval.select_next_some() => {
                    self.refresh_global_data_summary();
                }
                _ = progress_check_interval.select_next_some() => {
                    self.check_progress_of_all_data_streams();
                }
            }
        }
    }

    /// Handles new stream request messages from clients
    fn handle_stream_request_message(&mut self, request_message: StreamRequestMessage) {
        if let StreamRequest::TerminateStream(request) = request_message.stream_request {
            // Process the feedback request
            if let Err(error) = self.process_terminate_stream_request(&request) {
                error!(LogSchema::new(LogEntry::HandleTerminateRequest)
                    .event(LogEvent::Error)
                    .error(&error));
            }
            return;
        }

        // Process the stream request
        let response = self.process_new_stream_request(&request_message);
        if let Err(error) = &response {
            error!(LogSchema::new(LogEntry::HandleStreamRequest)
                .event(LogEvent::Error)
                .error(error));
        }

        // Send the response to the client
        if let Err(error) = request_message.response_sender.send(response) {
            error!(LogSchema::new(LogEntry::RespondToStreamRequest)
                .event(LogEvent::Error)
                .message(&format!(
                    "Failed to send response for stream request: {:?}",
                    error
                )));
        }
    }

    /// Processes a request for terminating the stream that sent a specific
    /// notification ID.
    fn process_terminate_stream_request(
        &mut self,
        terminate_request: &TerminateStreamRequest,
    ) -> Result<(), Error> {
        // Increment the stream termination counter
        let notification_feedback = &terminate_request.notification_feedback;
        increment_counter(
            &metrics::TERMINATE_DATA_STREAM,
            notification_feedback.get_label().into(),
        );

        // Find the data stream that sent the notification
        let notification_id = &terminate_request.notification_id;
        let data_stream_ids = self.get_all_data_stream_ids();
        for data_stream_id in &data_stream_ids {
            let data_stream = self.get_data_stream(data_stream_id);
            if data_stream.sent_notification(notification_id) {
                info!(LogSchema::new(LogEntry::HandleTerminateRequest)
                    .stream_id(*data_stream_id)
                    .event(LogEvent::Success)
                    .message(&format!(
                        "Terminating the stream that sent notification ID: {:?}. Feedback: {:?}",
                        notification_id, notification_feedback,
                    )));
                data_stream.handle_notification_feedback(notification_id, notification_feedback)?;
                self.data_streams.remove(notification_id);
                return Ok(());
            }
        }

        panic!(
            "Unable to find the stream that sent notification ID: {:?}. Feedback: {:?}",
            notification_id, notification_feedback,
        );
    }

    /// Creates a new stream and ensures the data for that stream is available
    fn process_new_stream_request(
        &mut self,
        request_message: &StreamRequestMessage,
    ) -> Result<DataStreamListener, Error> {
        // Increment the stream creation counter
        increment_counter(
            &metrics::CREATE_DATA_STREAM,
            request_message.stream_request.get_label().into(),
        );

        // Refresh the cached global data summary
        self.refresh_global_data_summary();

        // Create a new data stream
        let stream_id = self.stream_id_generator.next();
        let (data_stream, stream_listener) = DataStream::new(
            self.config,
            stream_id,
            &request_message.stream_request,
            self.aptos_data_client.clone(),
            self.notification_id_generator.clone(),
            &self.global_data_summary.advertised_data,
        )?;

        // Verify the data stream can be fulfilled using the currently advertised data
        data_stream.ensure_data_is_available(&self.global_data_summary.advertised_data)?;

        // Store the data stream internally
        if self.data_streams.insert(stream_id, data_stream).is_some() {
            panic!(
                "Duplicate data stream found! This should not occur! ID: {:?}",
                stream_id,
            );
        }
        info!(LogSchema::new(LogEntry::HandleStreamRequest)
            .stream_id(stream_id)
            .event(LogEvent::Success)
            .message(&format!(
                "Stream created for request: {:?}",
                request_message
            )));

        // Return the listener
        Ok(stream_listener)
    }

    /// Refreshes the global data summary by communicating with the Aptos data client
    fn refresh_global_data_summary(&mut self) {
        if let Err(error) = self.fetch_global_data_summary() {
            increment_counter(
                &metrics::GLOBAL_DATA_SUMMARY_ERROR,
                error.get_label().into(),
            );
            sample!(
                SampleRate::Duration(Duration::from_secs(GLOBAL_DATA_REFRESH_LOG_FREQ_SECS)),
                error!(LogSchema::new(LogEntry::RefreshGlobalData)
                    .event(LogEvent::Error)
                    .error(&error))
            );
        }
    }

    fn fetch_global_data_summary(&mut self) -> Result<(), Error> {
        let global_data_summary = self.aptos_data_client.get_global_data_summary();
        if global_data_summary.is_empty() {
            sample!(
                SampleRate::Duration(Duration::from_secs(GLOBAL_DATA_REFRESH_LOG_FREQ_SECS)),
                info!(LogSchema::new(LogEntry::RefreshGlobalData)
                    .message("Latest global data summary is empty."))
            );
        } else {
            verify_optimal_chunk_sizes(&global_data_summary.optimal_chunk_sizes)?;
            self.global_data_summary = global_data_summary;
        }

        Ok(())
    }

    /// Ensures that all existing data streams are making progress
    fn check_progress_of_all_data_streams(&mut self) {
        let data_stream_ids = self.get_all_data_stream_ids();
        for data_stream_id in &data_stream_ids {
            if let Err(error) = self.update_progress_of_data_stream(data_stream_id) {
                if matches!(error, Error::NoDataToFetch(_)) {
                    sample!(
                        SampleRate::Duration(Duration::from_secs(
                            NO_DATA_TO_FETCH_LOG_FREQ_SECS
                        )),
                        info!(LogSchema::new(LogEntry::CheckStreamProgress)
                            .stream_id(*data_stream_id)
                            .event(LogEvent::Pending)
                            .error(&error))
                    );
                } else {
                    increment_counter(
                        &metrics::CHECK_STREAM_PROGRESS_ERROR,
                        error.get_label().into(),
                    );
                    error!(LogSchema::new(LogEntry::CheckStreamProgress)
                        .stream_id(*data_stream_id)
                        .event(LogEvent::Error)
                        .error(&error));
                }
            }
        }
    }

    /// Ensures that a data stream has in-flight data requests and handles
    /// any new responses that have arrived since we last checked.
    fn update_progress_of_data_stream(
        &mut self,
        data_stream_id: &DataStreamId,
    ) -> Result<(), Error> {
        let global_data_summary = self.global_data_summary.clone();

        let data_stream = self.get_data_stream_mut(data_stream_id);
        if !data_stream.data_requests_initialized() {
            // Initialize the request batch by sending out data client requests
            data_stream.initialize_data_requests(global_data_summary)?;
            info!(
                (LogSchema::new(LogEntry::InitializeStream)
                    .stream_id(*data_stream_id)
                    .event(LogEvent::Success)
                    .message("Data stream initialized."))
            );
        } else {
            // Process any data client requests that have received responses
            data_stream.process_data_responses(global_data_summary)?;
        }

        Ok(())
    }

    fn get_all_data_stream_ids(&self) -> Vec<DataStreamId> {
        self.data_streams
            .keys()
            .cloned()
            .collect::<Vec<DataStreamId>>()
    }

    /// Returns the data stream associated with the given `data_stream_id`.
    /// Note: this method assumes the caller has already verified the stream exists.
    fn get_data_stream(&self, data_stream_id: &DataStreamId) -> &DataStream<T> {
        self.data_streams.get(data_stream_id).unwrap_or_else(|| {
            panic!(
                "Expected a data stream with ID: {:?}, but found None!",
                data_stream_id
            )
        })
    }

    /// Returns the data stream associated with the given `data_stream_id`.
    /// Note: this method assumes the caller has already verified the stream exists.
    fn get_data_stream_mut(&mut self, data_stream_id: &DataStreamId) -> &mut DataStream<T> {
        self.data_streams
            .get_mut(data_stream_id)
            .unwrap_or_else(|| {
                panic!(
                    "Expected a data stream with ID: {:?}, but found None!",
                    data_stream_id
                )
            })
    }
}

/// Verifies that all optimal chunk sizes are valid (i.e., not zero). Returns an
/// error if a chunk size is 0.
fn verify_optimal_chunk_sizes(optimal_chunk_sizes: &OptimalChunkSizes) -> Result<(), Error> {
    if optimal_chunk_sizes.account_states_chunk_size == 0
        || optimal_chunk_sizes.epoch_chunk_size == 0
        || optimal_chunk_sizes.transaction_chunk_size == 0
        || optimal_chunk_sizes.transaction_output_chunk_size == 0
    {
        Err(Error::AptosDataClientResponseIsInvalid(format!(
            "Found at least one optimal chunk size of zero: {:?}",
            optimal_chunk_sizes
        )))
    } else {
        Ok(())
    }
}
<|endoftext|>


<commit_before>
#[crate_id="capnp-rpc"];
#[crate_type="bin"];

extern mod capnp;

extern mod extra;

pub mod async;

pub mod calculator_capnp;
pub mod rpc_capnp;
//pub mod rpc-twoparty_capnp;

pub mod testing {
    use capnp;
    use calculator_capnp::Calculator;
    use rpc_capnp::{Message, Return, CapDescriptor};
    use std::io::net;
    use std;

    pub fn connect(addr_str : &str) {
        let sockaddr = match std::from_str::FromStr::from_str(addr_str) {
            None => fail!("could not parse socket address: {}", addr_str),
            Some(a) => a
        };

        let mut stream = net::tcp::TcpStream::connect(sockaddr);

        capnp::message::MessageBuilder::new_default(|message| {
                let restore = message.init_root::<Message::Builder>().init_restore();
                restore.set_question_id(0);
                restore.init_object_id().set_as_text("calculator");

                capnp::serialize::write_message(&mut stream, message);
            });

        capnp::serialize::InputStreamMessageReader::new(
            &mut stream,
            capnp::message::DEFAULT_READER_OPTIONS,
            |message| {
                match message.get_root::<Message::Reader>().which() {
                    Some(Message::Return(ret)) => {
                        println!("got a return {}", ret.get_answer_id());
                        match ret.which() {
                            Some(Return::Results(payload)) => {
                                println!("with a payload");
                                let cap_table = payload.get_cap_table();
                                for ii in range(0, cap_table.size()) {
                                    match cap_table[ii].which() {
                                        Some(CapDescriptor::None(())) => {}
                                        Some(CapDescriptor::SenderHosted(id)) => {
                                            println!("sender hosted: {}", id);
                                        }
                                        _ => {}
                                    }
                                }
                            }
                            _ => {}
                        }
                    }
                    _ => {println!("something else") }
                }
            });

        capnp::message::MessageBuilder::new_default(|message| {
                let call = message.init_root::<Message::Builder>().init_call();
                call.set_question_id(1);
                let promised_answer = call.init_target().init_promised_answer();
                promised_answer.set_question_id(0);
                call.set_interface_id(0x97983392df35cc36);
                call.set_method_id(0);
                let payload = call.init_params();
                let exp = payload.init_content().init_as_struct::<Calculator::Expression::Builder>();
                exp.set_literal(1.23456);

                capnp::serialize::write_message(&mut stream, message);

            });

        capnp::serialize::InputStreamMessageReader::new(
            &mut stream,
            capnp::message::DEFAULT_READER_OPTIONS,
            |message| {
                match message.get_root::<Message::Reader>().which() {
                    Some(Message::Return(ret)) => {
                        println!("got a return {}", ret.get_answer_id());
                        match ret.which() {
                            Some(Return::Results(payload)) => {
                                println!("with a payload");
                                let cap_table = payload.get_cap_table();
                                for ii in range(0, cap_table.size()) {
                                    match cap_table[ii].which() {
                                        Some(CapDescriptor::None(())) => {}
                                        Some(CapDescriptor::SenderHosted(id)) => {
                                            println!("sender hosted: {}", id);
                                        }
                                        _ => {}
                                    }
                                }
                            }
                            Some(Return::Exception(_)) => {
                                println!("exception");
                            }
                            _ => {}
                        }
                    }
                    _ => {println!("something else") }
                }
            });

    }
}

pub fn main() {
    testing::connect(std::os::args()[1]);
}
<commit_msg>some rpc with a separate listener task<commit_after>
#[crate_id="capnp-rpc"];
#[crate_type="bin"];

extern mod capnp;

extern mod extra;

pub mod async;

pub mod calculator_capnp;
pub mod rpc_capnp;
//pub mod rpc-twoparty_capnp;

pub mod testing {
    use capnp;
    use calculator_capnp::Calculator;
    use rpc_capnp::{Message, Return, CapDescriptor};
    use std;

    pub fn connect<T : std::io::Writer>(out_stream : &mut T) {

        capnp::message::MessageBuilder::new_default(|message| {
                let restore = message.init_root::<Message::Builder>().init_restore();
                restore.set_question_id(0);
                restore.init_object_id().set_as_text("calculator");

                capnp::serialize::write_message(out_stream, message);
            });

        capnp::message::MessageBuilder::new_default(|message| {
                let call = message.init_root::<Message::Builder>().init_call();
                call.set_question_id(1);
                let promised_answer = call.init_target().init_promised_answer();
                promised_answer.set_question_id(0);
                call.set_interface_id(0x97983392df35cc36);
                call.set_method_id(0);
                let payload = call.init_params();
                let exp = payload.init_content().init_as_struct::<Calculator::Expression::Builder>();
                exp.set_literal(1.23456);

                capnp::serialize::write_message(out_stream, message);

            });

    }
}

pub fn main() {
    use std::io::process;
    use capnp::message::MessageReader;
    use rpc_capnp::{Message, Return, CapDescriptor};

    let args = ~[std::os::args()[1].to_owned(), std::os::args()[2].to_owned()];

    let io = [process::CreatePipe(true, false), // stdin
              process::CreatePipe(false, true), // stdout
              process::InheritFd(2)];

    let config = process::ProcessConfig {
        program: "nc",
        args: args,
        env : None,
        cwd: None,
        io : io
    };
    let mut p = process::Process::new(config).unwrap();

    p.io.pop();
    let childStdOut = p.io.pop();
    let mut childStdIn = p.io.pop();

    do spawn || {
        let mut r = childStdOut;

        loop {

            let message = capnp::serialize::new_reader(
                &mut r,
                capnp::message::DEFAULT_READER_OPTIONS);
            match message.get_root::<Message::Reader>().which() {
                Some(Message::Return(ret)) => {
                    println!("got a return {}", ret.get_answer_id());
                    match ret.which() {
                        Some(Return::Results(payload)) => {
                            println!("with a payload");
                            let cap_table = payload.get_cap_table();
                            for ii in range(0, cap_table.size()) {
                                match cap_table[ii].which() {
                                    Some(CapDescriptor::None(())) => {}
                                    Some(CapDescriptor::SenderHosted(id)) => {
                                        println!("sender hosted: {}", id);
                                    }
                                    _ => {}
                                }
                            }
                        }
                        Some(Return::Exception(_)) => {
                            println!("exception");
                        }
                        _ => {}
                    }
                }
                Some(Message::Unimplemented(_)) => {
                    println!("unimplemented");
                }
                Some(Message::Abort(exc)) => {
                    println!("abort: {}", exc.get_reason());
                }
                None => { println!("Nothing there") }
                _ => {println!("something else") }
            }

        }
    }

    testing::connect(&mut childStdIn);

    p.wait();
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! A linked-list implementation using `RawLink`s.
use super::rawlink::RawLink;

use core::marker::PhantomData;
use core::ptr::Unique;
#[cfg(test)] mod test;

pub unsafe trait OwnedRef<T> {
    unsafe fn from_raw(ptr: *mut T) -> Self;
    unsafe fn take(self);
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

pub trait Node: Sized {
    fn next(&self) -> &RawLink<Self>;
    fn prev(&self) -> &RawLink<Self>;

    fn next_mut(&mut self) -> &mut RawLink<Self>;
    fn prev_mut(&mut self) -> &mut RawLink<Self>;
}

pub struct List<T, N>
where T: OwnedRef<N>
    , N: Node {
    head: RawLink<N>
  , tail: RawLink<N>
  , _ty_marker: PhantomData<T>
 }

 // impl<T> Node for List<T>
 // where T: OwnedRef
 //     , T: Node {
 //
 //    fn next(&self) -> &RawLink<Self> { &self.head }
 //    fn prev(&self) -> &RawLink<Self> { &self.tail }
 //
 //    fn next_mut(&mut self) -> &mut RawLink<Self> { self.head }
 //    fn prev_mut(&mut self) -> &mut RawLink<Self> { self.tail }
 // }
impl<T, N> List<T, N>
where T: OwnedRef<N>
    , N: Node {

    pub const fn new() -> Self {
        List { head: RawLink::none()
                 , tail: RawLink::none()
                 , _ty_marker: PhantomData }
    }

    pub fn front(&self) -> Option<&N> {
        unsafe { self.head.resolve() }
    }

    pub fn back(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }

    pub fn front_mut(&mut self) -> Option<&mut N> {
        unsafe { self.head.resolve_mut() }
    }

    pub fn back_mut(&mut self) -> Option<&mut N> {
        unsafe { self.tail.resolve_mut() }
    }

    pub fn is_empty(&self) -> bool {
        self.head.is_none()
    }

    pub fn push_front(&mut self, mut item: T) {
        unsafe {
            match self.head.resolve_mut() {
                None => {
                    // If this node's head is empty, set the pushed item's
                    // links to None, and make this node's tail point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.tail = RawLink::some(item.get_mut());
                }
              , Some(head) => {
                    // If this node is not empty, set the pushed item's tail
                    // to point at the head node, and make the head node's tail
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::some(head);
                    *item.get_mut().prev_mut() = RawLink::none();
                    *head.prev_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.head = RawLink::some(item.get_mut());
            item.take()
        }
    }

    pub fn push_back(&mut self, mut item: T) {
        unsafe {
            match self.tail.resolve_mut() {
                None => {
                    // If this node's tail is empty, set the pushed item's
                    // links to  None, and make this node's head point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.head = RawLink::some(item.get_mut());
                }
              , Some(tail) => {
                    // If this node is not empty, set the pushed item's head
                    // to point at the tail node, and make the tail node's head
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::some(tail);
                    *tail.next_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.tail = RawLink::some(item.get_mut());
            item.take()
        }
    }

    pub fn pop_front(&mut self) -> Option<T> {
        unsafe {
            self.head.take().resolve_mut()
                .map(|head| {
                    // mem::swap( &mut self.head
                    //          , head.next_mut().resolve_mut()
                    //                .map(|next| next.prev_mut())
                    //                .unwrap_or(&mut RawLink::none()) );
                    match head.next_mut().resolve_mut() {
                        None => self.tail = RawLink::none()
                      , Some(next) => {
                            *next.prev_mut() = RawLink::none();
                            self.head = RawLink::some(next);
                        }
                    }
                    T::from_raw(head)
                })
        }
    }

    pub fn pop_back(&mut self) -> Option<T> {
        unsafe {
            self.tail.take().resolve_mut()
                .map(|tail| {
                    match tail.prev_mut().resolve_mut() {
                        None => self.head = RawLink::none()
                      , Some(prev) => {
                            *prev.next_mut() = RawLink::none();
                            self.tail = RawLink::some(prev);
                        }
                    }
                    T::from_raw(tail)
                })
        }
    }

    pub fn peek_front(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }
}

pub struct ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {
        list: &'a mut List<T, N>
      , current: RawLink<N>
}

impl<'a, T, N> ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {

    pub fn next(&mut self) -> Option<&mut N> {
        unsafe {
            match self.current.take().resolve_mut() {
                None => self.list.head.resolve_mut()
                            .and_then(|head| {
                                self.current = RawLink::some(head);
                                self.current.resolve_mut()
                            })
              , Some(thing) => {
                    self.current = match thing.next_mut().resolve_mut() {
                        None => RawLink::none()
                      , Some(other_thing) => RawLink::some(other_thing)
                    };
                    self.current.resolve_mut()
                }
            }
        }
    }

    pub fn peek_next(&mut self) -> Option<&mut N> {
        unsafe {
            self.current.resolve_mut()
                .map_or( self.list.front_mut()
                       , |next| next.next_mut().resolve_mut())
        }
    }

}

// impl<'a, T, N> Iterator for ListCursor<'a, T, N>
// where T: OwnedRef<N>
//     , T: 'a
//     , N: Node
//     , N: 'a {
//     type Item = &'a mut N;
//
//     fn next<'b: 'a>(&'b mut self) -> Option<&'a mut N> {
//         self.next()
//     }
// }

//
// unsafe impl<T> OwnedRef for Unique<T> where T: Node {
//
//     #[inline]
//     fn take(self) {}
//
//     unsafe fn from_raw(ptr: *mut T) -> Self {
//         Unique::new(ptr)
//     }
// }
//
// unsafe impl<'a, T> OwnedRef<T> for &'a mut T {
//     #
//     #[inline] unsafe fn from_raw(raw: *mut T) -> &'a mut T {
//         &mut *raw
//     }
//
//     #[inline] unsafe fn take(self) {
//         forget(self);
//     }
// }
//

unsafe impl<T> OwnedRef<T> for Unique<T>  {
    #[inline]
    fn get(&self) -> &T { unsafe { self.get() } }

    #[inline]
    fn get_mut(&mut self) -> &mut T { unsafe { self.get_mut() } }

    #[inline]
    unsafe fn take(self) {}

    unsafe fn from_raw(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(any(test, feature = "use-std"))]
unsafe impl<T> OwnedRef<T> for ::std::boxed::Box<T> {

    fn get(&self) -> &T { &**self }
    fn get_mut(&mut self) -> &mut T { &mut **self }

    #[inline] unsafe fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}
<commit_msg>[intrusive] Linked lists now track length<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
//! A linked-list implementation using `RawLink`s.
use super::rawlink::RawLink;

use core::marker::PhantomData;
use core::ptr::Unique;
#[cfg(test)] mod test;

pub unsafe trait OwnedRef<T> {
    unsafe fn from_raw(ptr: *mut T) -> Self;
    unsafe fn take(self);
    fn get(&self) -> &T;
    fn get_mut(&mut self) -> &mut T;
}

pub trait Node: Sized {
    fn next(&self) -> &RawLink<Self>;
    fn prev(&self) -> &RawLink<Self>;

    fn next_mut(&mut self) -> &mut RawLink<Self>;
    fn prev_mut(&mut self) -> &mut RawLink<Self>;
}

pub struct List<T, N>
where T: OwnedRef<N>
    , N: Node {
    head: RawLink<N>
  , tail: RawLink<N>
  , _ty_marker: PhantomData<T>
  , length: usize
 }

 // impl<T> Node for List<T>
 // where T: OwnedRef
 //     , T: Node {
 //
 //    fn next(&self) -> &RawLink<Self> { &self.head }
 //    fn prev(&self) -> &RawLink<Self> { &self.tail }
 //
 //    fn next_mut(&mut self) -> &mut RawLink<Self> { self.head }
 //    fn prev_mut(&mut self) -> &mut RawLink<Self> { self.tail }
 // }
impl<T, N> List<T, N>
where T: OwnedRef<N>
    , N: Node {

    pub const fn new() -> Self {
        List { head: RawLink::none()
             , tail: RawLink::none()
             , _ty_marker: PhantomData
             , length: 0 }
    }

    #[inline] pub fn len(&self) -> usize {
        self.length
    }

    pub fn front(&self) -> Option<&N> {
        unsafe { self.head.resolve() }
    }

    pub fn back(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }

    pub fn front_mut(&mut self) -> Option<&mut N> {
        unsafe { self.head.resolve_mut() }
    }

    pub fn back_mut(&mut self) -> Option<&mut N> {
        unsafe { self.tail.resolve_mut() }
    }

    pub fn is_empty(&self) -> bool {
        self.head.is_none()
    }

    pub fn push_front(&mut self, mut item: T) {
        unsafe {
            match self.head.resolve_mut() {
                None => {
                    // If this node's head is empty, set the pushed item's
                    // links to None, and make this node's tail point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.tail = RawLink::some(item.get_mut());
                }
              , Some(head) => {
                    // If this node is not empty, set the pushed item's tail
                    // to point at the head node, and make the head node's tail
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::some(head);
                    *item.get_mut().prev_mut() = RawLink::none();
                    *head.prev_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.head = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    pub fn push_back(&mut self, mut item: T) {
        unsafe {
            match self.tail.resolve_mut() {
                None => {
                    // If this node's tail is empty, set the pushed item's
                    // links to  None, and make this node's head point to the
                    // pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::none();
                    self.head = RawLink::some(item.get_mut());
                }
              , Some(tail) => {
                    // If this node is not empty, set the pushed item's head
                    // to point at the tail node, and make the tail node's head
                    // point to the pushed item
                    *item.get_mut().next_mut() = RawLink::none();
                    *item.get_mut().prev_mut() = RawLink::some(tail);
                    *tail.next_mut() = RawLink::some(item.get_mut());
                }
            }
            // then, set this node's head pointer to point to the pushed item
            self.tail = RawLink::some(item.get_mut());
            item.take();
            self.length += 1;
        }
    }

    pub fn pop_front(&mut self) -> Option<T> {
        unsafe {
            self.head.take().resolve_mut()
                .map(|head| {
                    // mem::swap( &mut self.head
                    //          , head.next_mut().resolve_mut()
                    //                .map(|next| next.prev_mut())
                    //                .unwrap_or(&mut RawLink::none()) );
                    match head.next_mut().resolve_mut() {
                        None => self.tail = RawLink::none()
                      , Some(next) => {
                            *next.prev_mut() = RawLink::none();
                            self.head = RawLink::some(next);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(head)
                })
        }
    }

    pub fn pop_back(&mut self) -> Option<T> {
        unsafe {
            self.tail.take().resolve_mut()
                .map(|tail| {
                    match tail.prev_mut().resolve_mut() {
                        None => self.head = RawLink::none()
                      , Some(prev) => {
                            *prev.next_mut() = RawLink::none();
                            self.tail = RawLink::some(prev);
                        }
                    }
                    self.length -= 1;
                    T::from_raw(tail)
                })
        }
    }

    pub fn peek_front(&self) -> Option<&N> {
        unsafe { self.tail.resolve() }
    }
}

pub struct ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {
        list: &'a mut List<T, N>
      , current: RawLink<N>
}

impl<'a, T, N> ListCursor<'a, T, N>
where T: OwnedRef<N>
    , T: 'a
    , N: Node
    , N: 'a {

    pub fn next(&mut self) -> Option<&mut N> {
        unsafe {
            match self.current.take().resolve_mut() {
                None => self.list.head.resolve_mut()
                            .and_then(|head| {
                                self.current = RawLink::some(head);
                                self.current.resolve_mut()
                            })
              , Some(thing) => {
                    self.current = match thing.next_mut().resolve_mut() {
                        None => RawLink::none()
                      , Some(other_thing) => RawLink::some(other_thing)
                    };
                    self.current.resolve_mut()
                }
            }
        }
    }

    pub fn peek_next(&mut self) -> Option<&mut N> {
        unsafe {
            self.current.resolve_mut()
                .map_or( self.list.front_mut()
                       , |next| next.next_mut().resolve_mut())
        }
    }

}

// impl<'a, T, N> Iterator for ListCursor<'a, T, N>
// where T: OwnedRef<N>
//     , T: 'a
//     , N: Node
//     , N: 'a {
//     type Item = &'a mut N;
//
//     fn next<'b: 'a>(&'b mut self) -> Option<&'a mut N> {
//         self.next()
//     }
// }

//
// unsafe impl<T> OwnedRef for Unique<T> where T: Node {
//
//     #[inline]
//     fn take(self) {}
//
//     unsafe fn from_raw(ptr: *mut T) -> Self {
//         Unique::new(ptr)
//     }
// }
//
// unsafe impl<'a, T> OwnedRef<T> for &'a mut T {
//     #
//     #[inline] unsafe fn from_raw(raw: *mut T) -> &'a mut T {
//         &mut *raw
//     }
//
//     #[inline] unsafe fn take(self) {
//         forget(self);
//     }
// }
//

unsafe impl<T> OwnedRef<T> for Unique<T>  {
    #[inline]
    fn get(&self) -> &T { unsafe { self.get() } }

    #[inline]
    fn get_mut(&mut self) -> &mut T { unsafe { self.get_mut() } }

    #[inline]
    unsafe fn take(self) {}

    unsafe fn from_raw(ptr: *mut T) -> Self {
        Unique::new(ptr)
    }
}

#[cfg(any(test, feature = "use-std"))]
unsafe impl<T> OwnedRef<T> for ::std::boxed::Box<T> {

    fn get(&self) -> &T { &**self }
    fn get_mut(&mut self) -> &mut T { &mut **self }

    #[inline] unsafe fn take(self) {
        ::std::boxed::Box::into_raw(self);
    }

    unsafe fn from_raw(ptr: *mut T) -> Self {
        ::std::boxed::Box::from_raw(ptr)
    }
}
<|endoftext|>


<commit_before>use core::num::Wrapping;

macro_rules! wrapping_operation {
    ($result:expr, $lhs:ident $op:tt $rhs:expr) => {
        assert_eq!($result, $lhs $op $rhs);
        assert_eq!($result, &$lhs $op $rhs);
        assert_eq!($result, $lhs $op &$rhs);
        assert_eq!($result, &$lhs $op &$rhs);
    };
    ($result:expr, $op:tt $expr:expr) => {
        assert_eq!($result, $op $expr);
        assert_eq!($result, $op &$expr);
    };
}

macro_rules! wrapping_assignment {
    ($result:expr, $lhs:ident $op:tt $rhs:expr) => {
        let mut lhs1 = $lhs;
        lhs1 $op $rhs;
        assert_eq!($result, lhs1);

        let mut lhs2 = $lhs;
        lhs2 $op &$rhs;
        assert_eq!($result, lhs2);
    };
}

macro_rules! wrapping_test {
    ($type:ty, $min:expr, $max:expr) => {
        #[test]
        fn wrapping_$type() {
            let zero: Wrapping<$type> = Wrapping(0);
            let one: Wrapping<$type> = Wrapping(1);
            let min: Wrapping<$type> = Wrapping($min);
            let max: Wrapping<$type> = Wrapping($max);

            wrapping_operation!(min, max + one);
            wrapping_assignment!(min, max += one);
            wrapping_operation!(max, min - one);
            wrapping_assignment!(max, min -= one);
            wrapping_operation!(max, max * one);
            wrapping_assignment!(max, max *= one);
            wrapping_operation!(max, max / one);
            wrapping_assignment!(max, max /= one);
            wrapping_operation!(zero, max % one);
            wrapping_assignment!(zero, max %= one);
            wrapping_operation!(zero, zero & max);
            wrapping_assignment!(zero, zero &= max);
            wrapping_operation!(max, zero | max);
            wrapping_assignment!(max, zero |= max);
            wrapping_operation!(zero, max ^ max);
            wrapping_assignment!(zero, max ^= max);
            wrapping_operation!(zero, zero << 1usize);
            wrapping_assignment!(zero, zero <<= 1usize);
            wrapping_operation!(zero, zero >> 1usize);
            wrapping_assignment!(zero, zero >>= 1usize);
            wrapping_operation!(zero, -zero);
            wrapping_operation!(max, !min);
        }
    };
}

#[cfg(tests)]
mod tests {
    wrapping_test!(i8, i8::MIN, i8::MAX);
    wrapping_test!(i16, i16::MIN, i16::MAX);
    wrapping_test!(i32, i32::MIN, i32::MAX);
    wrapping_test!(i64, i64::MIN, i64::MAX);
    #[cfg(not(target_os = "emscripten"))]
    wrapping_test!(i128, i128::MIN, i128::MAX);
    wrapping_test!(isize, isize::MIN, isize::MAX);
    wrapping_test!(u8, u8::MIN, u8::MAX);
    wrapping_test!(u16, u16::MIN, u16::MAX);
    wrapping_test!(u32, u32::MIN, u32::MAX);
    wrapping_test!(u64, u64::MIN, u64::MAX);
    #[cfg(not(target_os = "emscripten"))]
    wrapping_test!(u128, u128::MIN, u128::MAX);
    wrapping_test!(usize, usize::MIN, usize::MAX);
}
<commit_msg>Remove unnecessary mod-cfg<commit_after>use core::num::Wrapping;

macro_rules! wrapping_operation {
    ($result:expr, $lhs:ident $op:tt $rhs:expr) => {
        assert_eq!($result, $lhs $op $rhs);
        assert_eq!($result, &$lhs $op $rhs);
        assert_eq!($result, $lhs $op &$rhs);
        assert_eq!($result, &$lhs $op &$rhs);
    };
    ($result:expr, $op:tt $expr:expr) => {
        assert_eq!($result, $op $expr);
        assert_eq!($result, $op &$expr);
    };
}

macro_rules! wrapping_assignment {
    ($result:expr, $lhs:ident $op:tt $rhs:expr) => {
        let mut lhs1 = $lhs;
        lhs1 $op $rhs;
        assert_eq!($result, lhs1);

        let mut lhs2 = $lhs;
        lhs2 $op &$rhs;
        assert_eq!($result, lhs2);
    };
}

macro_rules! wrapping_test {
    ($type:ty, $min:expr, $max:expr) => {
        #[test]
        fn wrapping_$type() {
            let zero: Wrapping<$type> = Wrapping(0);
            let one: Wrapping<$type> = Wrapping(1);
            let min: Wrapping<$type> = Wrapping($min);
            let max: Wrapping<$type> = Wrapping($max);

            wrapping_operation!(min, max + one);
            wrapping_assignment!(min, max += one);
            wrapping_operation!(max, min - one);
            wrapping_assignment!(max, min -= one);
            wrapping_operation!(max, max * one);
            wrapping_assignment!(max, max *= one);
            wrapping_operation!(max, max / one);
            wrapping_assignment!(max, max /= one);
            wrapping_operation!(zero, max % one);
            wrapping_assignment!(zero, max %= one);
            wrapping_operation!(zero, zero & max);
            wrapping_assignment!(zero, zero &= max);
            wrapping_operation!(max, zero | max);
            wrapping_assignment!(max, zero |= max);
            wrapping_operation!(zero, max ^ max);
            wrapping_assignment!(zero, max ^= max);
            wrapping_operation!(zero, zero << 1usize);
            wrapping_assignment!(zero, zero <<= 1usize);
            wrapping_operation!(zero, zero >> 1usize);
            wrapping_assignment!(zero, zero >>= 1usize);
            wrapping_operation!(zero, -zero);
            wrapping_operation!(max, !min);
        }
    };
}

wrapping_test!(i8, i8::MIN, i8::MAX);
wrapping_test!(i16, i16::MIN, i16::MAX);
wrapping_test!(i32, i32::MIN, i32::MAX);
wrapping_test!(i64, i64::MIN, i64::MAX);
#[cfg(not(target_os = "emscripten"))]
wrapping_test!(i128, i128::MIN, i128::MAX);
wrapping_test!(isize, isize::MIN, isize::MAX);
wrapping_test!(u8, u8::MIN, u8::MAX);
wrapping_test!(u16, u16::MIN, u16::MAX);
wrapping_test!(u32, u32::MIN, u32::MAX);
wrapping_test!(u64, u64::MIN, u64::MAX);
#[cfg(not(target_os = "emscripten"))]
wrapping_test!(u128, u128::MIN, u128::MAX);
wrapping_test!(usize, usize::MIN, usize::MAX);
<|endoftext|>