<commit_before>// Extracting metadata from crate files

import driver::session;
import syntax::{ast, ast_util};
import lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
import front::attr;
import middle::resolve;
import syntax::visit;
import syntax::codemap::span;
import back::x86;
import util::common;
import std::{vec, str, fs, io, option};
import std::option::{none, some};
import std::map::{hashmap, new_int_hash};
import syntax::print::pprust;
import common::*;

export read_crates;
export list_file_metadata;

// Traverses an AST, reading all the information about use'd crates and native
// libraries necessary for later resolving, typechecking, linking, etc.
fn read_crates(sess: session::session, crate: ast::crate) {
    let e =
        @{sess: sess,
          crate_cache: @std::map::new_str_hash::<int>(),
          library_search_paths: sess.get_opts().library_search_paths,
          mutable next_crate_num: 1};
    let v =
        visit::mk_simple_visitor(@{visit_view_item:
                                       bind visit_view_item(e, _),
                                   visit_item: bind visit_item(e, _)
                                      with *visit::default_simple_visitor()});
    visit::visit_crate(crate, (), v);
}

type env =
    @{sess: session::session,
      crate_cache: @hashmap<str, int>,
      library_search_paths: [str],
      mutable next_crate_num: ast::crate_num};

fn visit_view_item(e: env, i: @ast::view_item) {
    alt i.node {
      ast::view_item_use(ident, meta_items, id) {
        let cnum = resolve_crate(e, ident, meta_items, i.span);
        cstore::add_use_stmt_cnum(e.sess.get_cstore(), id, cnum);
      }
      _ { }
    }
}

fn visit_item(e: env, i: @ast::item) {
    alt i.node {
      ast::item_native_mod(m) {
        if m.abi != ast::native_abi_rust && m.abi != ast::native_abi_cdecl {
            ret;
        }
        let cstore = e.sess.get_cstore();
        if !cstore::add_used_library(cstore, m.native_name) { ret; }
        for a: ast::attribute in
            attr::find_attrs_by_name(i.attrs, "link_args") {
            alt attr::get_meta_item_value_str(attr::attr_meta(a)) {
              some(linkarg) { cstore::add_used_link_args(cstore, linkarg); }
              none. {/* fallthrough */ }
            }
        }
      }
      _ { }
    }
}

// A diagnostic function for dumping crate metadata to an output stream
fn list_file_metadata(path: str, out: io::writer) {
    alt get_metadata_section(path) {
      option::some(bytes) { decoder::list_crate_metadata(bytes, out); }
      option::none. {
        out.write_str("Could not find metadata in " + path + ".\n");
      }
    }
}

fn metadata_matches(crate_data: @[u8], metas: [@ast::meta_item]) -> bool {
    let attrs = decoder::get_crate_attributes(crate_data);
    let linkage_metas = attr::find_linkage_metas(attrs);

    log #fmt["matching %u metadata requirements against %u items",
             vec::len(metas), vec::len(linkage_metas)];

    for needed: @ast::meta_item in metas {
        if !attr::contains(linkage_metas, needed) {
            log #fmt["missing %s", pprust::meta_item_to_str(*needed)];
            ret false;
        }
    }
    ret true;
}

fn default_native_lib_naming(sess: session::session, static: bool) ->
   {prefix: str, suffix: str} {
    if static { ret {prefix: "lib", suffix: ".rlib"}; }
    alt sess.get_targ_cfg().os {
      session::os_win32. { ret {prefix: "", suffix: ".dll"}; }
      session::os_macos. { ret {prefix: "lib", suffix: ".dylib"}; }
      session::os_linux. { ret {prefix: "lib", suffix: ".so"}; }
    }
}

fn find_library_crate(sess: session::session, ident: ast::ident,
                      metas: [@ast::meta_item], library_search_paths: [str])
   -> option::t<{ident: str, data: @[u8]}> {

    attr::require_unique_names(sess, metas);

    // FIXME: Probably want a warning here since the user
    // is using the wrong type of meta item
    let crate_name =
        {
            let name_items = attr::find_meta_items_by_name(metas, "name");
            alt vec::last(name_items) {
              some(i) {
                alt attr::get_meta_item_value_str(i) {
                  some(n) { n }
                  _ { ident }
                }
              }
              none. { ident }
            }
        };

    let nn = default_native_lib_naming(sess, sess.get_opts().static);
    let x =
        find_library_crate_aux(nn, crate_name, metas, library_search_paths);
    if x != none || sess.get_opts().static { ret x; }
    let nn2 = default_native_lib_naming(sess, true);
    ret find_library_crate_aux(nn2, crate_name, metas, library_search_paths);
}

fn find_library_crate_aux(nn: {prefix: str, suffix: str}, crate_name: str,
                          metas: [@ast::meta_item],
                          library_search_paths: [str]) ->
   option::t<{ident: str, data: @[u8]}> {
    let prefix: str = nn.prefix + crate_name;
    let suffix: str = nn.suffix;
    // FIXME: we could probably use a 'glob' function in std::fs but it will
    // be much easier to write once the unsafe module knows more about FFI
    // tricks. Currently the glob(3) interface is a bit more than we can
    // stomach from here, and writing a C++ wrapper is more work than just
    // manually filtering fs::list_dir here.

    for library_search_path: str in library_search_paths {
        log #fmt["searching %s", library_search_path];
        for path: str in fs::list_dir(library_search_path) {
            log #fmt["searching %s", path];
            let f: str = fs::basename(path);
            if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
                log #fmt["skipping %s, doesn't look like %s*%s", path, prefix,
                         suffix];
                cont;
            }
            alt get_metadata_section(path) {
              option::some(cvec) {
                if !metadata_matches(cvec, metas) {
                    log #fmt["skipping %s, metadata doesn't match", path];
                    cont;
                }
                log #fmt["found %s with matching metadata", path];
                ret some({ident: path, data: cvec});
              }
              _ { }
            }
        }
    }
    ret none;
}

fn get_metadata_section(filename: str) -> option::t<@[u8]> {
    let mb = str::as_buf(filename, {|buf|
        llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
    });
    if mb as int == 0 { ret option::none::<@[u8]>; }
    let of = mk_object_file(mb);
    let si = mk_section_iter(of.llof);
    while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
        let name_buf = llvm::LLVMGetSectionName(si.llsi);
        let name = str::str_from_cstr(name_buf);
        if str::eq(name, x86::get_meta_sect_name()) {
            let cbuf = llvm::LLVMGetSectionContents(si.llsi);
            let csz = llvm::LLVMGetSectionSize(si.llsi);
            let cvbuf: *u8 = std::unsafe::reinterpret_cast(cbuf);
            ret option::some::<@[u8]>(@vec::unsafe::from_buf(cvbuf, csz));
        }
        llvm::LLVMMoveToNextSection(si.llsi);
    }
    ret option::none::<@[u8]>;
}

fn load_library_crate(sess: session::session, span: span, ident: ast::ident,
                      metas: [@ast::meta_item], library_search_paths: [str])
   -> {ident: str, data: @[u8]} {

    alt find_library_crate(sess, ident, metas, library_search_paths) {
      some(t) { ret t; }
      none. {
        sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
      }
    }
}

fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
                 span: span) -> ast::crate_num {
    if !e.crate_cache.contains_key(ident) {
        let cinfo =
            load_library_crate(e.sess, span, ident, metas,
                               e.library_search_paths);

        let cfilename = cinfo.ident;
        let cdata = cinfo.data;

        // Claim this crate number and cache it
        let cnum = e.next_crate_num;
        e.crate_cache.insert(ident, cnum);
        e.next_crate_num += 1;

        // Now resolve the crates referenced by this crate
        let cnum_map = resolve_crate_deps(e, cdata);

        let cmeta = {name: ident, data: cdata, cnum_map: cnum_map};

        let cstore = e.sess.get_cstore();
        cstore::set_crate_data(cstore, cnum, cmeta);
        cstore::add_used_crate_file(cstore, cfilename);
        ret cnum;
    } else { ret e.crate_cache.get(ident); }
}

// Go through the crate metadata and load any crates that it references
fn resolve_crate_deps(e: env, cdata: @[u8]) -> cstore::cnum_map {
    log "resolving deps of external crate";
    // The map from crate numbers in the crate we're resolving to local crate
    // numbers
    let cnum_map = new_int_hash::<ast::crate_num>();
    for dep: decoder::crate_dep in decoder::get_crate_deps(cdata) {
        let extrn_cnum = dep.cnum;
        let cname = dep.ident;
        log #fmt["resolving dep %s", cname];
        if e.crate_cache.contains_key(cname) {
            log "already have it";
            // We've already seen this crate
            let local_cnum = e.crate_cache.get(cname);
            cnum_map.insert(extrn_cnum, local_cnum);
        } else {
            log "need to load it";
            // This is a new one so we've got to load it
            // FIXME: Need better error reporting than just a bogus span
            let fake_span = ast_util::dummy_sp();
            let local_cnum = resolve_crate(e, cname, [], fake_span);
            cnum_map.insert(extrn_cnum, local_cnum);
        }
    }
    ret cnum_map;
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<commit_msg>rustc: Track link_args attributes on C stack cdecl natives as well<commit_after>// Extracting metadata from crate files

import driver::session;
import syntax::{ast, ast_util};
import lib::llvm::{False, llvm, mk_object_file, mk_section_iter};
import front::attr;
import middle::resolve;
import syntax::visit;
import syntax::codemap::span;
import back::x86;
import util::common;
import std::{vec, str, fs, io, option};
import std::option::{none, some};
import std::map::{hashmap, new_int_hash};
import syntax::print::pprust;
import common::*;

export read_crates;
export list_file_metadata;

// Traverses an AST, reading all the information about use'd crates and native
// libraries necessary for later resolving, typechecking, linking, etc.
fn read_crates(sess: session::session, crate: ast::crate) {
    let e =
        @{sess: sess,
          crate_cache: @std::map::new_str_hash::<int>(),
          library_search_paths: sess.get_opts().library_search_paths,
          mutable next_crate_num: 1};
    let v =
        visit::mk_simple_visitor(@{visit_view_item:
                                       bind visit_view_item(e, _),
                                   visit_item: bind visit_item(e, _)
                                      with *visit::default_simple_visitor()});
    visit::visit_crate(crate, (), v);
}

type env =
    @{sess: session::session,
      crate_cache: @hashmap<str, int>,
      library_search_paths: [str],
      mutable next_crate_num: ast::crate_num};

fn visit_view_item(e: env, i: @ast::view_item) {
    alt i.node {
      ast::view_item_use(ident, meta_items, id) {
        let cnum = resolve_crate(e, ident, meta_items, i.span);
        cstore::add_use_stmt_cnum(e.sess.get_cstore(), id, cnum);
      }
      _ { }
    }
}

fn visit_item(e: env, i: @ast::item) {
    alt i.node {
      ast::item_native_mod(m) {
        if m.abi != ast::native_abi_rust && m.abi != ast::native_abi_cdecl &&
                m.abi != ast::native_abi_c_stack_cdecl {
            ret;
        }
        let cstore = e.sess.get_cstore();
        if !cstore::add_used_library(cstore, m.native_name) { ret; }
        for a: ast::attribute in
            attr::find_attrs_by_name(i.attrs, "link_args") {
            alt attr::get_meta_item_value_str(attr::attr_meta(a)) {
              some(linkarg) { cstore::add_used_link_args(cstore, linkarg); }
              none. {/* fallthrough */ }
            }
        }
      }
      _ { }
    }
}

// A diagnostic function for dumping crate metadata to an output stream
fn list_file_metadata(path: str, out: io::writer) {
    alt get_metadata_section(path) {
      option::some(bytes) { decoder::list_crate_metadata(bytes, out); }
      option::none. {
        out.write_str("Could not find metadata in " + path + ".\n");
      }
    }
}

fn metadata_matches(crate_data: @[u8], metas: [@ast::meta_item]) -> bool {
    let attrs = decoder::get_crate_attributes(crate_data);
    let linkage_metas = attr::find_linkage_metas(attrs);

    log #fmt["matching %u metadata requirements against %u items",
             vec::len(metas), vec::len(linkage_metas)];

    for needed: @ast::meta_item in metas {
        if !attr::contains(linkage_metas, needed) {
            log #fmt["missing %s", pprust::meta_item_to_str(*needed)];
            ret false;
        }
    }
    ret true;
}

fn default_native_lib_naming(sess: session::session, static: bool) ->
   {prefix: str, suffix: str} {
    if static { ret {prefix: "lib", suffix: ".rlib"}; }
    alt sess.get_targ_cfg().os {
      session::os_win32. { ret {prefix: "", suffix: ".dll"}; }
      session::os_macos. { ret {prefix: "lib", suffix: ".dylib"}; }
      session::os_linux. { ret {prefix: "lib", suffix: ".so"}; }
    }
}

fn find_library_crate(sess: session::session, ident: ast::ident,
                      metas: [@ast::meta_item], library_search_paths: [str])
   -> option::t<{ident: str, data: @[u8]}> {

    attr::require_unique_names(sess, metas);

    // FIXME: Probably want a warning here since the user
    // is using the wrong type of meta item
    let crate_name =
        {
            let name_items = attr::find_meta_items_by_name(metas, "name");
            alt vec::last(name_items) {
              some(i) {
                alt attr::get_meta_item_value_str(i) {
                  some(n) { n }
                  _ { ident }
                }
              }
              none. { ident }
            }
        };

    let nn = default_native_lib_naming(sess, sess.get_opts().static);
    let x =
        find_library_crate_aux(nn, crate_name, metas, library_search_paths);
    if x != none || sess.get_opts().static { ret x; }
    let nn2 = default_native_lib_naming(sess, true);
    ret find_library_crate_aux(nn2, crate_name, metas, library_search_paths);
}

fn find_library_crate_aux(nn: {prefix: str, suffix: str}, crate_name: str,
                          metas: [@ast::meta_item],
                          library_search_paths: [str]) ->
   option::t<{ident: str, data: @[u8]}> {
    let prefix: str = nn.prefix + crate_name;
    let suffix: str = nn.suffix;
    // FIXME: we could probably use a 'glob' function in std::fs but it will
    // be much easier to write once the unsafe module knows more about FFI
    // tricks. Currently the glob(3) interface is a bit more than we can
    // stomach from here, and writing a C++ wrapper is more work than just
    // manually filtering fs::list_dir here.

    for library_search_path: str in library_search_paths {
        log #fmt["searching %s", library_search_path];
        for path: str in fs::list_dir(library_search_path) {
            log #fmt["searching %s", path];
            let f: str = fs::basename(path);
            if !(str::starts_with(f, prefix) && str::ends_with(f, suffix)) {
                log #fmt["skipping %s, doesn't look like %s*%s", path, prefix,
                         suffix];
                cont;
            }
            alt get_metadata_section(path) {
              option::some(cvec) {
                if !metadata_matches(cvec, metas) {
                    log #fmt["skipping %s, metadata doesn't match", path];
                    cont;
                }
                log #fmt["found %s with matching metadata", path];
                ret some({ident: path, data: cvec});
              }
              _ { }
            }
        }
    }
    ret none;
}

fn get_metadata_section(filename: str) -> option::t<@[u8]> {
    let mb = str::as_buf(filename, {|buf|
        llvm::LLVMRustCreateMemoryBufferWithContentsOfFile(buf)
    });
    if mb as int == 0 { ret option::none::<@[u8]>; }
    let of = mk_object_file(mb);
    let si = mk_section_iter(of.llof);
    while llvm::LLVMIsSectionIteratorAtEnd(of.llof, si.llsi) == False {
        let name_buf = llvm::LLVMGetSectionName(si.llsi);
        let name = str::str_from_cstr(name_buf);
        if str::eq(name, x86::get_meta_sect_name()) {
            let cbuf = llvm::LLVMGetSectionContents(si.llsi);
            let csz = llvm::LLVMGetSectionSize(si.llsi);
            let cvbuf: *u8 = std::unsafe::reinterpret_cast(cbuf);
            ret option::some::<@[u8]>(@vec::unsafe::from_buf(cvbuf, csz));
        }
        llvm::LLVMMoveToNextSection(si.llsi);
    }
    ret option::none::<@[u8]>;
}

fn load_library_crate(sess: session::session, span: span, ident: ast::ident,
                      metas: [@ast::meta_item], library_search_paths: [str])
   -> {ident: str, data: @[u8]} {

    alt find_library_crate(sess, ident, metas, library_search_paths) {
      some(t) { ret t; }
      none. {
        sess.span_fatal(span, #fmt["can't find crate for '%s'", ident]);
      }
    }
}

fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
                 span: span) -> ast::crate_num {
    if !e.crate_cache.contains_key(ident) {
        let cinfo =
            load_library_crate(e.sess, span, ident, metas,
                               e.library_search_paths);

        let cfilename = cinfo.ident;
        let cdata = cinfo.data;

        // Claim this crate number and cache it
        let cnum = e.next_crate_num;
        e.crate_cache.insert(ident, cnum);
        e.next_crate_num += 1;

        // Now resolve the crates referenced by this crate
        let cnum_map = resolve_crate_deps(e, cdata);

        let cmeta = {name: ident, data: cdata, cnum_map: cnum_map};

        let cstore = e.sess.get_cstore();
        cstore::set_crate_data(cstore, cnum, cmeta);
        cstore::add_used_crate_file(cstore, cfilename);
        ret cnum;
    } else { ret e.crate_cache.get(ident); }
}

// Go through the crate metadata and load any crates that it references
fn resolve_crate_deps(e: env, cdata: @[u8]) -> cstore::cnum_map {
    log "resolving deps of external crate";
    // The map from crate numbers in the crate we're resolving to local crate
    // numbers
    let cnum_map = new_int_hash::<ast::crate_num>();
    for dep: decoder::crate_dep in decoder::get_crate_deps(cdata) {
        let extrn_cnum = dep.cnum;
        let cname = dep.ident;
        log #fmt["resolving dep %s", cname];
        if e.crate_cache.contains_key(cname) {
            log "already have it";
            // We've already seen this crate
            let local_cnum = e.crate_cache.get(cname);
            cnum_map.insert(extrn_cnum, local_cnum);
        } else {
            log "need to load it";
            // This is a new one so we've got to load it
            // FIXME: Need better error reporting than just a bogus span
            let fake_span = ast_util::dummy_sp();
            let local_cnum = resolve_crate(e, cname, [], fake_span);
            cnum_map.insert(extrn_cnum, local_cnum);
        }
    }
    ret cnum_map;
}

// Local Variables:
// mode: rust
// fill-column: 78;
// indent-tabs-mode: nil
// c-basic-offset: 4
// buffer-file-coding-system: utf-8-unix
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
// End:
<|endoftext|>


<commit_before>//! The AWS SQS API.

#![cfg_attr(feature = "nightly-testing", allow(while_let_loop))]

include!(concat!(env!("OUT_DIR"), "/sqs.rs"));

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use sqs::{SqsClient, SendMessageRequest, MessageAttributeValue};

    use super::super::{Region, SignedRequest};
    use super::super::mock::*;

    extern crate env_logger;

    #[test]
    fn should_serialize_map_parameters_in_query_string() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <SendMessageResponse>
			    <SendMessageResult>
			        <MD5OfMessageBody>
			            fafb00f5732ab283681e124bf8747ed1
			        </MD5OfMessageBody>
			        <MD5OfMessageAttributes>
				    3ae8f24a165a8cedc005670c81a27295
			        </MD5OfMessageAttributes>
			        <MessageId>
			            5fea7756-0ea4-451a-a703-a558b933e274
			        </MessageId>
			    </SendMessageResult>
			    <ResponseMetadata>
			        <RequestId>
			            27daac76-34dd-47df-bd01-1f6e873584a0
			        </RequestId>
			    </ResponseMetadata>
			</SendMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(None, request.payload);
                assert_eq!(Some(&Some("test_attribute_name".to_owned())),
                           request.params.get("MessageAttribute.1.Name"));
                assert_eq!(Some(&Some("test_attribute_value".to_owned())),
                           request.params.get("MessageAttribute.1.Value.StringValue"));
                assert_eq!(Some(&Some("String".to_owned())),
                           request.params.get("MessageAttribute.1.Value.DataType"));
            });

        let mut message_attributes = HashMap::new();

        message_attributes.insert("test_attribute_name".to_owned(),
                                  MessageAttributeValue {
                                      string_value: Some("test_attribute_value".to_owned()),
                                      data_type: "String".to_owned(),
                                      ..Default::default()
                                  });
        let request = SendMessageRequest {
            message_body: "foo".to_owned(),
            queue_url: "bar".to_owned(),
            message_attributes: Some(message_attributes),
            ..Default::default()
        };

        let client =
            SqsClient::with_request_dispatcher(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.send_message(&request).unwrap();
    }
}
<commit_msg>add a unit test for the SQS module that verifies #323 is fixed<commit_after>//! The AWS SQS API.

#![cfg_attr(feature = "nightly-testing", allow(while_let_loop))]

include!(concat!(env!("OUT_DIR"), "/sqs.rs"));

#[cfg(test)]
mod test {
    use std::collections::HashMap;
    use sqs::{SqsClient, SendMessageRequest, ReceiveMessageRequest, MessageAttributeValue};

    use super::super::{Region, SignedRequest};
    use super::super::mock::*;

    extern crate env_logger;

    #[test]
    fn should_serialize_map_parameters_in_query_string() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <SendMessageResponse>
              <SendMessageResult>
                  <MD5OfMessageBody>
                      fafb00f5732ab283681e124bf8747ed1
                  </MD5OfMessageBody>
                  <MD5OfMessageAttributes>
                3ae8f24a165a8cedc005670c81a27295
                  </MD5OfMessageAttributes>
                  <MessageId>
                      5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
              </SendMessageResult>
              <ResponseMetadata>
                  <RequestId>
                      27daac76-34dd-47df-bd01-1f6e873584a0
                  </RequestId>
              </ResponseMetadata>
            </SendMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                assert_eq!(None, request.payload);
                assert_eq!(Some(&Some("test_attribute_name".to_owned())),
                           request.params.get("MessageAttribute.1.Name"));
                assert_eq!(Some(&Some("test_attribute_value".to_owned())),
                           request.params.get("MessageAttribute.1.Value.StringValue"));
                assert_eq!(Some(&Some("String".to_owned())),
                           request.params.get("MessageAttribute.1.Value.DataType"));
            });

        let mut message_attributes = HashMap::new();

        message_attributes.insert("test_attribute_name".to_owned(),
                                  MessageAttributeValue {
                                      string_value: Some("test_attribute_value".to_owned()),
                                      data_type: "String".to_owned(),
                                      ..Default::default()
                                  });
        let request = SendMessageRequest {
            message_body: "foo".to_owned(),
            queue_url: "bar".to_owned(),
            message_attributes: Some(message_attributes),
            ..Default::default()
        };

        let client =
            SqsClient::with_request_dispatcher(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.send_message(&request).unwrap();
    }

    #[test]
    fn should_fix_issue_323() {
        let mock = MockRequestDispatcher::with_status(200)
            .with_body(r#"<?xml version="1.0" encoding="UTF-8"?>
            <ReceiveMessageResponse>
              <ReceiveMessageResult>
                <Message>
                  <MessageId>
                    5fea7756-0ea4-451a-a703-a558b933e274
                  </MessageId>
                  <ReceiptHandle>
                    MbZj6wDWli+JvwwJaBV+3dcjk2YW2vA3+STFFljTM8tJJg6HRG6PYSasuWXPJB+Cw
                    Lj1FjgXUv1uSj1gUPAWV66FU/WeR4mq2OKpEGYWbnLmpRCJVAyeMjeU5ZBdtcQ+QE
                    auMZc8ZRv37sIW2iJKq3M9MFx1YvV11A2x/KSbkJ0=
                  </ReceiptHandle>
                  <MD5OfBody>
                    fafb00f5732ab283681e124bf8747ed1
                  </MD5OfBody>
                  <Body>This is a test message</Body>
                  <Attribute>
                    <Name>SenderId</Name>
                    <Value>195004372649</Value>
                  </Attribute>
                </Message>
              </ReceiveMessageResult>
              <ResponseMetadata>
                <RequestId>
                  b6633655-283d-45b4-aee4-4e84e0ae6afa
                </RequestId>
              </ResponseMetadata>
          </ReceiveMessageResponse>"#)
            .with_request_checker(|request: &SignedRequest| {
                assert_eq!("POST", request.method);
                assert_eq!("/", request.path);
                // assert_eq!(None, request.payload);
                assert_eq!(request.params.get("Action"), Some(&Some("ReceiveMessage".to_owned())));
                assert_eq!(request.params.get("MaxNumberOfMessages"), Some(&Some("1".to_owned())));
                assert_eq!(request.params.get("VisibilityTimeout"), Some(&Some("2".to_owned())));
                assert_eq!(request.params.get("WaitTimeSeconds"), Some(&Some("3".to_owned())));
                assert_eq!(request.params.get("Integer"), None);
            });

        let request = ReceiveMessageRequest {
          max_number_of_messages: Some(1),
          queue_url: "foo".to_owned(),
          visibility_timeout: Some(2),
          wait_time_seconds: Some(3),
            ..Default::default()
        };

        let client = SqsClient::with_request_dispatcher(mock, MockCredentialsProvider, Region::UsEast1);
        let _result = client.receive_message(&request).unwrap();
    }
}
<|endoftext|>


<commit_before>use std::io::prelude::*;
use std::net;
use std::io;
use std::convert::From;

extern crate rustc_serialize;
use rustc_serialize::json;
use rustc_serialize::Encodable;

extern crate time;

pub struct Fluentd<'a, A: net::ToSocketAddrs> {
    pub address: A,
    pub tag: &'a str,
}

pub enum FluentError {
    DecodeError(json::EncoderError),
    IoError(io::Error),
}

impl From<io::Error> for FluentError {
    fn from(err: io::Error) -> FluentError {
        FluentError::IoError(err)
    }
}

impl From<json::EncoderError> for FluentError {
    fn from(err: json::EncoderError) -> FluentError {
        FluentError::DecodeError(err)
    }
}

impl <'a, A: net::ToSocketAddrs> Fluentd<'a, A> {
    pub fn write<B: Encodable> (&self, object: &B) -> Result<(), FluentError> {
        let tag = try!(json::encode(&self.tag));
        let now = time::now();
        let record = try!(json::encode(object));
        let message = format!("[{},{},{}]", tag, now.to_timespec().sec, record);

        let mut stream = try!(net::TcpStream::connect(&self.address));
        let _ = stream.write(&message.into_bytes());
        drop(stream);

        Ok(())
    }
}
<commit_msg>Implement Debug trait<commit_after>use std::io::prelude::*;
use std::net;
use std::io;
use std::convert::From;

extern crate rustc_serialize;
use rustc_serialize::json;
use rustc_serialize::Encodable;

extern crate time;

pub struct Fluentd<'a, A: net::ToSocketAddrs> {
    pub address: A,
    pub tag: &'a str,
}

#[derive(Debug)]
pub enum FluentError {
    DecodeError(json::EncoderError),
    IoError(io::Error),
}

impl From<io::Error> for FluentError {
    fn from(err: io::Error) -> FluentError {
        FluentError::IoError(err)
    }
}

impl From<json::EncoderError> for FluentError {
    fn from(err: json::EncoderError) -> FluentError {
        FluentError::DecodeError(err)
    }
}

impl <'a, A: net::ToSocketAddrs> Fluentd<'a, A> {
    pub fn write<B: Encodable> (&self, object: &B) -> Result<(), FluentError> {
        let tag = try!(json::encode(&self.tag));
        let now = time::now();
        let record = try!(json::encode(object));
        let message = format!("[{},{},{}]", tag, now.to_timespec().sec, record);

        let mut stream = try!(net::TcpStream::connect(&self.address));
        let _ = stream.write(&message.into_bytes());
        drop(stream);

        Ok(())
    }
}
<|endoftext|>


<commit_before>use na::{Mat2, DMat};
use std::collections::HashMap;
use std::num::*;
use itertools::Itertools;
use std::cell::RefCell;
use std::rc::Rc;

mod test;

impl Default for DStreamProps {
    fn default() -> DStreamProps {
        DStreamProps {
            c_m: 3.0,
            c_l: 0.8,
            lambda: 0.998,
            beta: 0.3,
            i_bins: 10 as usize,
            j_bins: 10 as usize,
            i_range: (-10.0, 10.0),
            j_range: (-10.0, 10.0),
        }
    }
}
pub struct DStreamProps {
    c_m: f64,
    c_l: f64,
    lambda: f64,
    beta: f64,
    i_bins: usize,
    j_bins: usize,
    i_range: (f64, f64),
    j_range: (f64, f64),
}

#[derive(Clone)]
pub struct RawData {
    x: f64,
    y: f64,
    v: f64,
}

#[derive(Clone)]
#[derive(Debug)]
#[derive(Copy)]
struct BucketPoint {
    t: u32,
    v: f64,
}
#[derive(Clone)]
struct GridData {
    i: usize,
    j: usize,
    v: f64,
}
struct TheWorld {
    g_vec: Vec<((usize, usize), DG)>,
}

#[test]
fn test_new_put_works() {
    let raw_data_1 = RawData{x: 1.0, y: -1.0, v: 123.45};
    let raw_data_2 = RawData{x: 5.0, y: -7.0, v: 23.45};
    let raw_data_3 = RawData{x: 5.0, y: -7.0, v: 83.45};
    let raw_data_4 = RawData{x: 15.0, y: -17.0, v: 83.45};

    let rd_vec = vec!(raw_data_1, raw_data_2, raw_data_3, raw_data_4);

    let t = 1;

    let default_vec : Vec<BucketPoint> = Vec::new();
    let mut world = TheWorld{g_vec: Vec::new()};
    world.init(default_vec);
    let res1 = world.put(t, rd_vec.clone());
    let res2 = world.put(t + 1, rd_vec.clone());
    let res3 = world.put(t + 2, rd_vec.clone());

}

impl TheWorld {

    #[test]
    fn test_which_grid() {
        let loc = (-6., 6.);
        let i_rn = (-10.0, 10.0);
        let j_rn = (-10.0, 10.0);
        let i_bins = 10 as usize;
        let j_bins = 10 as usize;

        let result = TheWorld::which_grid(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
        assert_eq!((2, 8), result);

    }
    fn which_grid(val: (f64, f64), i_range: (f64, f64), j_range: (f64, f64), i_bins: usize, j_bins: usize) -> Result<(usize, usize), String> {
        let i_size = (i_range.1 - i_range.0) / i_bins as f64;
        let i_number_of_sizes = ((val.0 - i_range.0) / i_size) as usize;
        let j_size = (j_range.1 - j_range.0) / j_bins as f64;
        let j_number_of_sizes = ((val.1 - j_range.0) / j_size) as usize;

        assert!(i_number_of_sizes < i_bins);
        assert!(j_number_of_sizes < j_bins);

        Ok((i_number_of_sizes, j_number_of_sizes))
    }

    fn init(&mut self, def_bucket: Vec<BucketPoint>) {
        println!("init");
        let props: DStreamProps = DStreamProps { ..Default::default() };

        for i in 0..props.i_bins {
            for j in 0..props.j_bins {
                let z_clone = def_bucket.clone();
                let some_default_dg = DG {i: i, j: j, updates_and_vals: z_clone};
                (self.g_vec).push(((i as usize, j as usize), some_default_dg));
            }
        }
    }
    fn do_time_steps() {}
    fn do_one_time_step(t: u32, data: Vec<RawData>) {}

    fn get_by_idx(&mut self, idx: (usize, usize))-> DG {
        let  vec_f: Vec<((usize, usize), DG)> = self.g_vec.clone().into_iter().filter(|i| i.0 == idx).collect();
        vec_f[0].1.clone()
    }
    fn update_by_idx(&mut self, idx: (usize, usize), dg: DG) -> Result<(), String> {
        self.g_vec.retain(|i| i.0 != idx);
        self.g_vec.push((idx, dg));
        Ok(())
    }
    fn put(&mut self, t: u32, dat: Vec<RawData>) -> Result<(), String> {

        fn validate_range(loc2d: (f64, f64)) -> bool {

            let props: DStreamProps = DStreamProps { ..Default::default() };

            if ((loc2d.0 <= props.i_range.1) &&
            (loc2d.0 >= props.i_range.0) &&
            (loc2d.1 <= props.j_range.1) &&
            (loc2d.1 >= props.j_range.0)) {
                println!("valid!");
            } else {
                println!("invalid! -- bad input range");
                return false
            }
            return true
        }
        let with_idxs: Vec<GridData> = dat
            .iter()
            .filter(|rd| validate_range((rd.x, rd.y)))
            .map(|rd| self.which_idxs(rd).unwrap())
            .collect();

        let props: DStreamProps = DStreamProps { ..Default::default() };

        for (key, group) in with_idxs.iter().group_by(|gd| (gd.i, gd.j)) {
            println!("--put: key, g size: ({},{}) : {}", key.0, key.1, group.len());

            let the_vec_of_vals: Vec<f64> = group.iter().map(|t| t.v).collect();

            let mut some_default_dg = DG {i: key.0, j: key.1, updates_and_vals: Vec::<BucketPoint>::new()};

            let teh_dg: &mut DG = &mut self.get_by_idx(key);
            let update_dg_result = teh_dg.update(t, the_vec_of_vals);
            let udpate_world_result = self.update_by_idx(key, teh_dg.clone());
        }
        Ok(())
    }
    fn which_idxs(&self, dat: &RawData) -> Result<GridData, String> {

        let props: DStreamProps = DStreamProps { ..Default::default() };

        let idxs = TheWorld::which_grid((dat.x, dat.y), props.i_range, props.j_range,props.i_bins, props.j_bins).unwrap();

        Ok((GridData{i:idxs.0,j:idxs.1,v:dat.v}))

    }
}

#[test]
fn test_dg_update_and_get() {
    let mut dg = DG {i: 0, j:0, updates_and_vals: Vec::new()};
    dg.update(1, vec!(100.0));

    dg.update(10, vec!(200.0));
    dg.update(20, vec!(300.0));

    assert_eq!((1, 100.0), dg.get_last_update_and_value_to(2));
    assert_eq!((10, 200.0), dg.get_last_update_and_value_to(14));
    assert_eq!((20, 300.0), dg.get_last_update_and_value_to(22));

    let v_at_t = dg.get_at_time(30);
    println!("v: {}", v_at_t);
}

#[derive(Debug)]
#[derive(Clone)]
//#[derive(Copy)] TODO: how to make this work?
struct DG {
    i: usize,
    j: usize,
    updates_and_vals: Vec<BucketPoint>,
}
impl DG {
    fn get_at_time(&self, t: u32) -> f64 {
        let last_update_time_and_value = self.get_last_update_and_value_to(t);
        let coeff = self.coeff(t, last_update_time_and_value.0);
        coeff * last_update_time_and_value.1 + 1.0
    }
    fn update(&mut self, t: u32, vals: Vec<f64>) -> Result<(), String> {
        let sum = vals.clone().iter().fold(0.0, |sum, x| sum + x);
        self.updates_and_vals.push(BucketPoint {t: t, v: sum});
        println!("  times updated dg: {}", self.updates_and_vals.len());
        Ok(())
    }

    fn get_last_update_and_value_to(&self, t: u32) -> (u32, f64) {
        let a: BucketPoint = self.updates_and_vals.clone().into_iter().filter(|bp| bp.t < t).max_by_key(|bp| bp.t).unwrap();
        let t_l = a.t;
        let v_l = a.v;
        println!("  last update relative to {} is (t: {}, v: {})", t, t_l, v_l);
        (t_l, v_l)
    }

    fn coeff(&self, t_n: u32, t_l: u32) -> f64 {
        let props: DStreamProps = DStreamProps { ..Default::default() };
        props.lambda.powf((t_n - t_l) as f64)
    }

 }

#[test]
fn test_initialize_clustering() {

    let result = initialize_clustering(Vec::new());
    assert_eq!(Ok(()), result);
}

pub fn initialize_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update density of all grids in grid_list
    //assign each dense grid to a distinct cluster
    //label all other grids as NO_CLASS; bad grids!
    /*
    do until no change in cluster labels
          foreach cluster c
            foreach outside grid g of c
                foreach neighboring grid h of g
                    if h belongs to cluster c'
                        if |c| > |c'| label all grids in c' as c
                        else label all grids in c as c'
                    else if (h is translational) label h as in c
    end do
    */
    Ok(())
}

pub fn adjust_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update the density of all grids in grid_list
    /*
    foreach grid g whose attribute (dense/sparse/transitional) is changed since last call to adjust_clustering()
        if g is a sparse grid
            delete g from its cluster c, label g as NO_CLASS
            if (c becomes unconnected) split c into two clusters
        else if g is a dense grid
            among all neighboring grids of g, find out the grid h whoe cluster c_h has the largest size
            if h is a dense grid
                if (g is labelled as NO_CLASS) label g as in c_h
                else if (g is in cluster c and |c| > |c_h|)
                    label all grids in c_h as in c
                else if (g is in cluster c and |c| <= |c_h|)
                    label all grids in c as in c_h
            else if h is a transitional grid
                if ((g is NO_CLASS) and (h is an outside grid if g is added to c_h)) label g as in c_h
                else if (g is in cluster c and |c| >= |c_h|)
                    move h from cluster c_h to c
        else if (g is transitional grid)
            among neighboring clusters of g, find the largest one c'
            satisfying that g is an outside grid if added to it and
            label g as in c'
    */

    Ok(())
}<commit_msg>removed as sporadic impl and test<commit_after>use na::{Mat2, DMat};
use std::collections::HashMap;
use std::num::*;
use itertools::Itertools;
use std::cell::RefCell;
use std::rc::Rc;

mod test;

impl Default for DStreamProps {
    fn default() -> DStreamProps {
        DStreamProps {
            c_m: 3.0,
            c_l: 0.8,
            lambda: 0.998,
            beta: 0.3,
            i_bins: 10 as usize,
            j_bins: 10 as usize,
            i_range: (-10.0, 10.0),
            j_range: (-10.0, 10.0),
        }
    }
}
pub struct DStreamProps {
    c_m: f64,
    c_l: f64,
    lambda: f64,
    beta: f64,
    i_bins: usize,
    j_bins: usize,
    i_range: (f64, f64),
    j_range: (f64, f64),
}

#[derive(Clone)]
pub struct RawData {
    x: f64,
    y: f64,
    v: f64,
}

#[derive(Clone)]
#[derive(Debug)]
#[derive(Copy)]
struct GridPoint {
    t: u32,
    v: f64,
}
#[derive(Clone)]
struct GridData {
    i: usize,
    j: usize,
    v: f64,
}
struct TheWorld {
    g_vec: Vec<((usize, usize), DG)>,
}

#[test]
fn test_new_put_works() {
    let raw_data_1 = RawData{x: 1.0, y: -1.0, v: 123.45};
    let raw_data_2 = RawData{x: 5.0, y: -7.0, v: 23.45};
    let raw_data_3 = RawData{x: 5.0, y: -7.0, v: 83.45};
    let raw_data_4 = RawData{x: 15.0, y: -17.0, v: 83.45};

    let rd_vec = vec!(raw_data_1, raw_data_2, raw_data_3, raw_data_4);

    let t = 1;

    let default_vec : Vec<GridPoint> = Vec::new();
    let mut world = TheWorld{g_vec: Vec::new()};
    world.init(default_vec);
    let res1 = world.put(t, rd_vec.clone());
    let res2 = world.put(t + 1, rd_vec.clone());
    let res3 = world.put(t + 2, rd_vec.clone());

}

impl TheWorld {

    #[test]
    fn test_which_grid() {
        let loc = (-6., 6.);
        let i_rn = (-10.0, 10.0);
        let j_rn = (-10.0, 10.0);
        let i_bins = 10 as usize;
        let j_bins = 10 as usize;

        let result = TheWorld::which_grid(loc, i_rn, j_rn, i_bins, j_bins).unwrap();
        assert_eq!((2, 8), result);

    }
    fn which_grid(val: (f64, f64), i_range: (f64, f64), j_range: (f64, f64), i_bins: usize, j_bins: usize) -> Result<(usize, usize), String> {
        let i_size = (i_range.1 - i_range.0) / i_bins as f64;
        let i_number_of_sizes = ((val.0 - i_range.0) / i_size) as usize;
        let j_size = (j_range.1 - j_range.0) / j_bins as f64;
        let j_number_of_sizes = ((val.1 - j_range.0) / j_size) as usize;

        assert!(i_number_of_sizes < i_bins);
        assert!(j_number_of_sizes < j_bins);

        Ok((i_number_of_sizes, j_number_of_sizes))
    }

    fn init(&mut self, def_bucket: Vec<GridPoint>) {
        println!("init");
        let props: DStreamProps = DStreamProps { ..Default::default() };

        for i in 0..props.i_bins {
            for j in 0..props.j_bins {
                let z_clone = def_bucket.clone();
                let some_default_dg = DG {i: i, j: j, updates_and_vals: z_clone, removed_as_spore_adic: Vec::new()};
                (self.g_vec).push(((i as usize, j as usize), some_default_dg));
            }
        }
    }
    fn do_time_steps() {}
    fn do_one_time_step(t: u32, data: Vec<RawData>) {}

    fn get_by_idx(&mut self, idx: (usize, usize))-> DG {
        let  vec_f: Vec<((usize, usize), DG)> = self.g_vec.clone().into_iter().filter(|i| i.0 == idx).collect();
        vec_f[0].1.clone()
    }
    fn update_by_idx(&mut self, idx: (usize, usize), dg: DG) -> Result<(), String> {
        self.g_vec.retain(|i| i.0 != idx);
        self.g_vec.push((idx, dg));
        Ok(())
    }
    fn put(&mut self, t: u32, dat: Vec<RawData>) -> Result<(), String> {

        fn validate_range(loc2d: (f64, f64)) -> bool {

            let props: DStreamProps = DStreamProps { ..Default::default() };

            if ((loc2d.0 <= props.i_range.1) &&
            (loc2d.0 >= props.i_range.0) &&
            (loc2d.1 <= props.j_range.1) &&
            (loc2d.1 >= props.j_range.0)) {
                println!("valid!");
            } else {
                println!("invalid! -- bad input range");
                return false
            }
            return true
        }
        let with_idxs: Vec<GridData> = dat
            .iter()
            .filter(|rd| validate_range((rd.x, rd.y)))
            .map(|rd| self.which_idxs(rd).unwrap())
            .collect();

        let props: DStreamProps = DStreamProps { ..Default::default() };

        for (key, group) in with_idxs.iter().group_by(|gd| (gd.i, gd.j)) {
            println!("--put: key, g size: ({},{}) : {}", key.0, key.1, group.len());

            let the_vec_of_vals: Vec<f64> = group.iter().map(|t| t.v).collect();

            let mut some_default_dg = DG {i: key.0, j: key.1, updates_and_vals: Vec::<GridPoint>::new(), removed_as_spore_adic: Vec::new()};

            let teh_dg: &mut DG = &mut self.get_by_idx(key);
            let update_dg_result = teh_dg.update(t, the_vec_of_vals);
            let udpate_world_result = self.update_by_idx(key, teh_dg.clone());
        }
        Ok(())
    }
    fn which_idxs(&self, dat: &RawData) -> Result<GridData, String> {

        let props: DStreamProps = DStreamProps { ..Default::default() };

        let idxs = TheWorld::which_grid((dat.x, dat.y), props.i_range, props.j_range,props.i_bins, props.j_bins).unwrap();

        Ok((GridData{i:idxs.0,j:idxs.1,v:dat.v}))

    }
}

#[test]
fn test_dg_update_and_get() {
    let mut dg = DG {i: 0, j:0, updates_and_vals: Vec::new(), removed_as_spore_adic: Vec::new()};
    dg.update(1, vec!(100.0));

    dg.update(10, vec!(200.0));
    dg.update(20, vec!(300.0));

    assert_eq!((1, 100.0), dg.get_last_update_and_value_to(2));
    assert_eq!((10, 200.0), dg.get_last_update_and_value_to(14));
    assert_eq!((20, 300.0), dg.get_last_update_and_value_to(22));

    let v_at_t = dg.get_at_time(30);
    println!("v: {}", v_at_t);
}

#[test]
fn test_removed_as_sporadic() {
    let mut dg = DG {i: 0, j:0, updates_and_vals: Vec::new(), removed_as_spore_adic: vec!(1, 2, 3, 4)};
    assert_eq!(1, dg.get_last_time_removed_as_sporadic_to(1));
    assert_eq!(2, dg.get_last_time_removed_as_sporadic_to(2));
    assert_eq!(4, dg.get_last_time_removed_as_sporadic_to(5));
}

#[derive(Debug)]
#[derive(Clone)]
//#[derive(Copy)] TODO: how to make this work?
struct DG {
    i: usize,
    j: usize,
    updates_and_vals: Vec<GridPoint>,
    removed_as_spore_adic: Vec<u32>,
}
impl DG {
    fn get_at_time(&self, t: u32) -> f64 {
        let last_update_time_and_value = self.get_last_update_and_value_to(t);
        let coeff = self.coeff(t, last_update_time_and_value.0);
        coeff * last_update_time_and_value.1 + 1.0
    }
    fn update(&mut self, t: u32, vals: Vec<f64>) -> Result<(), String> {
        let sum = vals.clone().iter().fold(0.0, |sum, x| sum + x);
        self.updates_and_vals.push(GridPoint {t: t, v: sum});
        println!("  times updated dg: {}", self.updates_and_vals.len());
        Ok(())
    }

    fn get_last_update_and_value_to(&self, t: u32) -> (u32, f64) {
        let a: GridPoint = self.updates_and_vals.clone().into_iter().filter(|bp| bp.t < t).max_by_key(|bp| bp.t).unwrap();
        let t_l = a.t;
        let v_l = a.v;
        println!("  last update relative to {} is (t: {}, v: {})", t, t_l, v_l);
        (t_l, v_l)
    }

    fn get_last_time_removed_as_sporadic_to(&self, t: u32) -> u32 {
        let t = self.removed_as_spore_adic.clone().into_iter().filter(|&the_t| the_t < t).max().unwrap();
        t
    }

    fn coeff(&self, t_n: u32, t_l: u32) -> f64 {
        let props: DStreamProps = DStreamProps { ..Default::default() };
        props.lambda.powf((t_n - t_l) as f64)
    }

 }

#[test]
fn test_initialize_clustering() {

    let result = initialize_clustering(Vec::new());
    assert_eq!(Ok(()), result);
}

pub fn initialize_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update density of all grids in grid_list
    //assign each dense grid to a distinct cluster
    //label all other grids as NO_CLASS; bad grids!
    /*
    do until no change in cluster labels
          foreach cluster c
            foreach outside grid g of c
                foreach neighboring grid h of g
                    if h belongs to cluster c'
                        if |c| > |c'| label all grids in c' as c
                        else label all grids in c as c'
                    else if (h is translational) label h as in c
    end do
    */
    Ok(())
}

pub fn adjust_clustering(grid_list: Vec<RawData>) -> Result<(), String> {
    //update the density of all grids in grid_list
    /*
    foreach grid g whose attribute (dense/sparse/transitional) is changed since last call to adjust_clustering()
        if g is a sparse grid
            delete g from its cluster c, label g as NO_CLASS
            if (c becomes unconnected) split c into two clusters
        else if g is a dense grid
            among all neighboring grids of g, find out the grid h whoe cluster c_h has the largest size
            if h is a dense grid
                if (g is labelled as NO_CLASS) label g as in c_h
                else if (g is in cluster c and |c| > |c_h|)
                    label all grids in c_h as in c
                else if (g is in cluster c and |c| <= |c_h|)
                    label all grids in c as in c_h
            else if h is a transitional grid
                if ((g is NO_CLASS) and (h is an outside grid if g is added to c_h)) label g as in c_h
                else if (g is in cluster c and |c| >= |c_h|)
                    move h from cluster c_h to c
        else if (g is transitional grid)
            among neighboring clusters of g, find the largest one c'
            satisfying that g is an outside grid if added to it and
            label g as in c'
    */

    Ok(())
}<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::fmt::{Display, self};
use std::str::FromStr;
use url::Url;
use url::ParseError as UrlError;

use Error;

/// The Request-URI of a Request's StartLine.
///
/// From Section 5.3, Request Target:
/// > Once an inbound connection is obtained, the client sends an HTTP
/// > request message (Section 3) with a request-target derived from the
/// > target URI.  There are four distinct formats for the request-target,
/// > depending on both the method being requested and whether the request
/// > is to a proxy.
/// >
/// > ```notrust
/// > request-target = origin-form
/// >                / absolute-form
/// >                / authority-form
/// >                / asterisk-form
/// > ```
///
/// # Uri explanations
///
/// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
/// |-|   |-------------------------------||--------| |-------------------| |-----|
///  |                  |                       |               |              |
/// scheme          authority                 path            query         fragment
#[derive(Clone)]
pub struct Uri {
    source: Cow<'static, str>,
    scheme_end: Option<usize>,
    authority_end: Option<usize>,
    query: Option<usize>,
    fragment: Option<usize>,
}

impl Uri {
    /// Parse a string into a `Uri`.
    pub fn new(s: &str) -> Result<Uri, Error> {
        let bytes = s.as_bytes();
        if bytes.len() == 0 {
            Err(Error::Uri(UrlError::RelativeUrlWithoutBase))
        } else if bytes == b"*" {
            Ok(Uri {
                source: "*".into(),
                scheme_end: None,
                authority_end: None,
                query: None,
                fragment: None,
            })
        } else if bytes == b"/" {
            Ok(Uri::default())
        } else if bytes.starts_with(b"/") {
            Ok(Uri {
                source: s.to_owned().into(),
                scheme_end: None,
                authority_end: None,
                query: parse_query(s),
                fragment: parse_fragment(s),
            })
        } else if s.contains("://") {
            Ok(Uri {
                source: s.to_owned().into(),
                scheme_end: parse_scheme(s),
                authority_end: parse_authority(s),
                query: parse_query(s),
                fragment: parse_fragment(s),
            })
        } else {
            Ok(Uri {
                source: s.to_owned().into(),
                scheme_end: None,
                authority_end: Some(s.len()),
                query: None,
                fragment: None,
            })
        }
    }

    /// Get the path of this `Uri`.
    pub fn path(&self) -> &str {
        let index = self.authority_end.unwrap_or(self.scheme_end.unwrap_or(0));
        let query_len = self.query.unwrap_or(0);
        let fragment_len = self.fragment.unwrap_or(0);
        let end = self.source.len() - if query_len > 0 { query_len + 1 } else { 0 } -
            if fragment_len > 0 { fragment_len + 1 } else { 0 };
        if index >= end {
            ""
        } else {
            &self.source[index..end]
        }
    }

    /// Get the scheme of this `Uri`.
    pub fn scheme(&self) -> Option<&str> {
        if let Some(end) = self.scheme_end {
            Some(&self.source[..end])
        } else {
            None
        }
    }

    /// Get the authority of this `Uri`.
    pub fn authority(&self) -> Option<&str> {
        if let Some(end) = self.authority_end {
            let index = self.scheme_end.map(|i| i + 3).unwrap_or(0);

            Some(&self.source[index..end])
        } else {
            None
        }
    }

    /// Get the host of this `Uri`.
    pub fn host(&self) -> Option<&str> {
        if let Some(auth) = self.authority() {
            auth.split(":").next()
        } else {
            None
        }
    }

    /// Get the port of this `Uri.
    pub fn port(&self) -> Option<u16> {
        if let Some(auth) = self.authority() {
            let v: Vec<&str> = auth.split(":").collect();
            if v.len() == 2 {
                u16::from_str(v[1]).ok()
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Get the query string of this `Uri`, starting after the `?`.
    pub fn query(&self) -> Option<&str> {
        let fragment_len = self.fragment.unwrap_or(0);
        let fragment_len = if fragment_len > 0 { fragment_len + 1 } else { 0 };
        if let Some(len) = self.query {
            Some(&self.source[self.source.len() - len - fragment_len..self.source.len() - fragment_len])
        } else {
            None
        }
    }

    #[cfg(test)]
    fn fragment(&self) -> Option<&str> {
        if let Some(len) = self.fragment {
            Some(&self.source[self.source.len() - len..])
        } else {
            None
        }
    }
}

fn parse_scheme(s: &str) -> Option<usize> {
    s.find(':')
}

fn parse_authority(s: &str) -> Option<usize> {
    let v: Vec<&str> = s.split("://").collect();
    let auth = v.last().unwrap()
        .split("/")
        .next()
        .unwrap_or(s)
        .len() + if v.len() == 2 { v[0].len() + 3 } else { 0 };

    return Some(auth);
}

fn parse_query(s: &str) -> Option<usize> {
    match s.find('?') {
        Some(i) => {
            let frag_pos = s.find('#').unwrap_or(s.len());

            return Some(frag_pos - i - 1);
        },
        None => None,
    }
}

fn parse_fragment(s: &str) -> Option<usize> {
    match s.find('#') {
        Some(i) => Some(s.len() - i - 1),
        None => None,
    }
}

impl FromStr for Uri {
    type Err = Error;

    fn from_str(s: &str) -> Result<Uri, Error> {
        Uri::new(s)
    }
}

impl From<Url> for Uri {
    fn from(url: Url) -> Uri {
        Uri::new(url.as_str()).expect("Uri::From<Url> failed")
    }
}

impl PartialEq for Uri {
    fn eq(&self, other: &Uri) -> bool {
        self.source == other.source
    }
}

impl AsRef<str> for Uri {
    fn as_ref(&self) -> &str {
        &self.source
    }
}

impl Default for Uri {
    fn default() -> Uri {
        Uri {
            source: "/".into(),
            scheme_end: None,
            authority_end: None,
            query: None,
            fragment: None,
        }
    }
}

impl fmt::Debug for Uri {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.source.as_ref(), f)
    }
}

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

macro_rules! test_parse {
    (
        $test_name:ident,
        $str:expr,
        $($method:ident = $value:expr,)*
    ) => (
        #[test]
        fn $test_name() {
            let uri = Uri::new($str).unwrap();
            $(
            assert_eq!(uri.$method(), $value);
            )+
        }
    );
}

test_parse! {
    test_uri_parse_origin_form,
    "/some/path/here?and=then&hello#and-bye",

    scheme = None,
    authority = None,
    path = "/some/path/here",
    query = Some("and=then&hello"),
    fragment = Some("and-bye"),
}

test_parse! {
    test_uri_parse_absolute_form,
    "http://127.0.0.1:61761/chunks",

    scheme = Some("http"),
    authority = Some("127.0.0.1:61761"),
    path = "/chunks",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_absolute_form_without_path,
    "https://127.0.0.1:61761",

    scheme = Some("https"),
    authority = Some("127.0.0.1:61761"),
    path = "/",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_asterisk_form,
    "*",

    scheme = None,
    authority = None,
    path = "*",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_authority_form,
    "localhost:3000",

    scheme = None,
    authority = Some("localhost:3000"),
    path = "",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_absolute_with_default_port_http,
    "http://127.0.0.1:80",

    scheme = Some("http"),
    authority = Some("127.0.0.1"),
    path = "/",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_absolute_with_default_port_https,
    "https://127.0.0.1:443",

    scheme = Some("https"),
    authority = Some("127.0.0.1"),
    path = "/",
    query = None,
    fragment = None,
}

#[test]
fn test_uri_parse_error() {
    fn err(s: &str) {
        Uri::new(s).unwrap_err();
    }

    err("http://");
    //TODO: these should error
    //err("htt:p//host");
    //err("hyper.rs/");
    //err("hyper.rs?key=val");
}

#[test]
fn test_uri_from_url() {
    let uri = Uri::from(Url::parse("http://test.com/nazghul?test=3").unwrap());
    assert_eq!(uri.path(), "/nazghul");
    assert_eq!(uri.authority(), Some("test.com"));
    assert_eq!(uri.scheme(), Some("http"));
    assert_eq!(uri.query(), Some("test=3"));
    assert_eq!(uri.as_ref(), "http://test.com/nazghul?test=3");
}
<commit_msg>refactor(uri): Add default path for absolute-form<commit_after>use std::borrow::Cow;
use std::fmt::{Display, self};
use std::str::FromStr;
use url::Url;
use url::ParseError as UrlError;

use Error;

/// The Request-URI of a Request's StartLine.
///
/// From Section 5.3, Request Target:
/// > Once an inbound connection is obtained, the client sends an HTTP
/// > request message (Section 3) with a request-target derived from the
/// > target URI.  There are four distinct formats for the request-target,
/// > depending on both the method being requested and whether the request
/// > is to a proxy.
/// >
/// > ```notrust
/// > request-target = origin-form
/// >                / absolute-form
/// >                / authority-form
/// >                / asterisk-form
/// > ```
///
/// # Uri explanations
///
/// abc://username:password@example.com:123/path/data?key=value&key2=value2#fragid1
/// |-|   |-------------------------------||--------| |-------------------| |-----|
///  |                  |                       |               |              |
/// scheme          authority                 path            query         fragment
#[derive(Clone)]
pub struct Uri {
    source: Cow<'static, str>,
    scheme_end: Option<usize>,
    authority_end: Option<usize>,
    query: Option<usize>,
    fragment: Option<usize>,
}

impl Uri {
    /// Parse a string into a `Uri`.
    pub fn new(s: &str) -> Result<Uri, Error> {
        let bytes = s.as_bytes();
        if bytes.len() == 0 {
            Err(Error::Uri(UrlError::RelativeUrlWithoutBase))
        } else if bytes == b"*" {
            Ok(Uri {
                source: "*".into(),
                scheme_end: None,
                authority_end: None,
                query: None,
                fragment: None,
            })
        } else if bytes == b"/" {
            Ok(Uri::default())
        } else if bytes.starts_with(b"/") {
            Ok(Uri {
                source: s.to_owned().into(),
                scheme_end: None,
                authority_end: None,
                query: parse_query(s),
                fragment: parse_fragment(s),
            })
        } else if s.contains("://") {
            Ok(Uri {
                source: s.to_owned().into(),
                scheme_end: parse_scheme(s),
                authority_end: parse_authority(s),
                query: parse_query(s),
                fragment: parse_fragment(s),
            })
        } else {
            Ok(Uri {
                source: s.to_owned().into(),
                scheme_end: None,
                authority_end: Some(s.len()),
                query: None,
                fragment: None,
            })
        }
    }

    /// Get the path of this `Uri`.
    pub fn path(&self) -> &str {
        let index = self.authority_end.unwrap_or(self.scheme_end.unwrap_or(0));
        let query_len = self.query.unwrap_or(0);
        let fragment_len = self.fragment.unwrap_or(0);
        let end = self.source.len() - if query_len > 0 { query_len + 1 } else { 0 } -
            if fragment_len > 0 { fragment_len + 1 } else { 0 };
        if index >= end {
            if self.scheme().is_some() {
                return "/" // absolute-form MUST have path
            }
            ""
        } else {
            &self.source[index..end]
        }
    }

    /// Get the scheme of this `Uri`.
    pub fn scheme(&self) -> Option<&str> {
        if let Some(end) = self.scheme_end {
            Some(&self.source[..end])
        } else {
            None
        }
    }

    /// Get the authority of this `Uri`.
    pub fn authority(&self) -> Option<&str> {
        if let Some(end) = self.authority_end {
            let index = self.scheme_end.map(|i| i + 3).unwrap_or(0);

            Some(&self.source[index..end])
        } else {
            None
        }
    }

    /// Get the host of this `Uri`.
    pub fn host(&self) -> Option<&str> {
        if let Some(auth) = self.authority() {
            auth.split(":").next()
        } else {
            None
        }
    }

    /// Get the port of this `Uri.
    pub fn port(&self) -> Option<u16> {
        if let Some(auth) = self.authority() {
            let v: Vec<&str> = auth.split(":").collect();
            if v.len() == 2 {
                u16::from_str(v[1]).ok()
            } else {
                None
            }
        } else {
            None
        }
    }

    /// Get the query string of this `Uri`, starting after the `?`.
    pub fn query(&self) -> Option<&str> {
        let fragment_len = self.fragment.unwrap_or(0);
        let fragment_len = if fragment_len > 0 { fragment_len + 1 } else { 0 };
        if let Some(len) = self.query {
            Some(&self.source[self.source.len() - len - fragment_len..self.source.len() - fragment_len])
        } else {
            None
        }
    }

    #[cfg(test)]
    fn fragment(&self) -> Option<&str> {
        if let Some(len) = self.fragment {
            Some(&self.source[self.source.len() - len..])
        } else {
            None
        }
    }
}

fn parse_scheme(s: &str) -> Option<usize> {
    s.find(':')
}

fn parse_authority(s: &str) -> Option<usize> {
    let v: Vec<&str> = s.split("://").collect();
    let auth = v.last().unwrap()
        .split("/")
        .next()
        .unwrap_or(s)
        .len() + if v.len() == 2 { v[0].len() + 3 } else { 0 };

    return Some(auth);
}

fn parse_query(s: &str) -> Option<usize> {
    match s.find('?') {
        Some(i) => {
            let frag_pos = s.find('#').unwrap_or(s.len());

            return Some(frag_pos - i - 1);
        },
        None => None,
    }
}

fn parse_fragment(s: &str) -> Option<usize> {
    match s.find('#') {
        Some(i) => Some(s.len() - i - 1),
        None => None,
    }
}

impl FromStr for Uri {
    type Err = Error;

    fn from_str(s: &str) -> Result<Uri, Error> {
        Uri::new(s)
    }
}

impl From<Url> for Uri {
    fn from(url: Url) -> Uri {
        Uri::new(url.as_str()).expect("Uri::From<Url> failed")
    }
}

impl PartialEq for Uri {
    fn eq(&self, other: &Uri) -> bool {
        self.source == other.source
    }
}

impl AsRef<str> for Uri {
    fn as_ref(&self) -> &str {
        &self.source
    }
}

impl Default for Uri {
    fn default() -> Uri {
        Uri {
            source: "/".into(),
            scheme_end: None,
            authority_end: None,
            query: None,
            fragment: None,
        }
    }
}

impl fmt::Debug for Uri {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Debug::fmt(&self.source.as_ref(), f)
    }
}

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

macro_rules! test_parse {
    (
        $test_name:ident,
        $str:expr,
        $($method:ident = $value:expr,)*
    ) => (
        #[test]
        fn $test_name() {
            let uri = Uri::new($str).unwrap();
            $(
            assert_eq!(uri.$method(), $value);
            )+
        }
    );
}

test_parse! {
    test_uri_parse_origin_form,
    "/some/path/here?and=then&hello#and-bye",

    scheme = None,
    authority = None,
    path = "/some/path/here",
    query = Some("and=then&hello"),
    fragment = Some("and-bye"),
}

test_parse! {
    test_uri_parse_absolute_form,
    "http://127.0.0.1:61761/chunks",

    scheme = Some("http"),
    authority = Some("127.0.0.1:61761"),
    path = "/chunks",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_absolute_form_without_path,
    "https://127.0.0.1:61761",

    scheme = Some("https"),
    authority = Some("127.0.0.1:61761"),
    path = "/",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_asterisk_form,
    "*",

    scheme = None,
    authority = None,
    path = "*",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_authority_form,
    "localhost:3000",

    scheme = None,
    authority = Some("localhost:3000"),
    path = "",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_absolute_with_default_port_http,
    "http://127.0.0.1:80",

    scheme = Some("http"),
    authority = Some("127.0.0.1:80"),
    path = "/",
    query = None,
    fragment = None,
}

test_parse! {
    test_uri_parse_absolute_with_default_port_https,
    "https://127.0.0.1:443",

    scheme = Some("https"),
    authority = Some("127.0.0.1:443"),
    path = "/",
    query = None,
    fragment = None,
}

#[test]
fn test_uri_parse_error() {
    fn err(s: &str) {
        Uri::new(s).unwrap_err();
    }

    err("http://");
    //TODO: these should error
    //err("htt:p//host");
    //err("hyper.rs/");
    //err("hyper.rs?key=val");
}

#[test]
fn test_uri_from_url() {
    let uri = Uri::from(Url::parse("http://test.com/nazghul?test=3").unwrap());
    assert_eq!(uri.path(), "/nazghul");
    assert_eq!(uri.authority(), Some("test.com"));
    assert_eq!(uri.scheme(), Some("http"));
    assert_eq!(uri.query(), Some("test=3"));
    assert_eq!(uri.as_ref(), "http://test.com/nazghul?test=3");
}
<|endoftext|>


<commit_before>//! Allows dynamic dispatch to object-unsafe traits, with some caveats.
//!
//! `list_of_types` works around Rust's lack of generic/associated statics by requiring the program to specify a single "list of types" at compile time, which must include everything that you want to call into dynamically. This must be globally unique within the program. That is, if a *library* wants to use these features, it must rely on being passed the global list as a generic parameter.
//!
//! Creating a list of types is simple: you wrap each type `T` into `ListedType<T>`, then put the `ListedType`s into tuples (possibly nested tuples). All the traits necessary to use a list for automatically implemented for all nested tuples of `ListedType`s. For instance, ((ListedType<i64>, ListedType<String>, ListedType<Vec<usize>>), ListedType<bool>) is a valid list with 4 types in it.

use std::marker::PhantomData;

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct ListedTypeIndex (usize);

#[macro_export]
macro_rules! time_steward_make_sublist {
  (mod $mod: ident visits $T: ident where $($where:tt)*) => {mod $mod {
    use std::marker::PhantomData;
    use std::any::Any;
    use $crate::dynamic::list_of_types::{List, ListedType, SubListRepresentative, GlobalListConscious};
    pub trait Visitor {
      fn visit<$T>(&mut self) where $($where)*;
    }
    pub unsafe trait SubList: List {
      fn visit_all<V: Visitor>(visitor: &mut V);
      fn count()->usize;
      fn count_before<T>()->usize;
    }
    unsafe impl <T: Any> SubList for ListedType<T> {
      #[inline(always)]
      default fn visit_all<V: Visitor>(_: &mut V) {}
      #[inline(always)]
      default fn count()->usize {0}
      #[inline(always)]
      default fn count_before<U>()->usize {panic!("invoked count_before on a list that doesn't contain the type")}
    }
    unsafe impl <$T: Any> SubList for ListedType<$T> where $($where)* {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        visitor.visit::<$T>();
      }
      #[inline(always)]
      fn count()->usize {1}
      #[inline(always)]
      fn count_before<U>()->usize {0}
    }
    __time_steward_internal_sublist_tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

    pub struct Representative <GlobalList: SubList> (PhantomData <GlobalList>,!);
    impl <GlobalList: SubList> GlobalListConscious for Representative <GlobalList> {
      type GlobalList = GlobalList;
    }
    unsafe impl <GlobalList: SubList> SubListRepresentative for Representative <GlobalList> {
      fn count()->usize {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        GlobalList::count()
      }
      fn index<T>()->$crate::dynamic::list_of_types::ListedTypeIndex {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        $crate::dynamic::list_of_types::ListedTypeIndex(GlobalList::count_before::<T>())
      }
    }/*{
      fn visit_all<V: Visitor>(visitor: &mut V) {
        GlobalList::visit_all(visitor);
      }
    }*/
  }}
}
pub struct ListedType<T: Any>(PhantomData <T>, !);

#[macro_export]
#[doc(hidden)]
macro_rules! __time_steward_internal_sublist_tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> SubList for ($($T,)* $TL,)
      where $($T: SubList,)* $TL: SubList
    {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        // note: visiting order must be the same as the order of count_before()
        $($T::visit_all(visitor);)*
        $TL::visit_all(visitor);
      }
      #[inline(always)]
      fn count()->usize {
        $($T::count() + )* $TL::count()
      }
      #[inline(always)]
      fn count_before<T>()->usize {
        // note: visiting order must be the same as the order of count_before()
        let count = 0;
        $(if $T::includes::<T> () {return count + $T::count_before::<T>()}
        let count = count + $T::count();)*
        if $TL::includes::<T> () {return count + $TL::count_before::<T>()}
        panic!("invoked count_before on a list that doesn't contain the type")
      }
    }
    __time_steward_internal_sublist_tuple_impls! ($($T),*);
  };
  () => {};
}

pub unsafe trait List: Any {
  fn includes <T> ()->bool;
}
pub trait GlobalListConscious {
  type GlobalList: List;
}
pub unsafe trait SubListRepresentative {
  fn count()->usize;
  fn index<T>()->ListedTypeIndex;
}

pub unsafe trait AmI <T> {fn am_i()->bool;}
unsafe impl <T, U> AmI <T> for U {default fn am_i()->bool {false}}
unsafe impl <T> AmI <T> for T {fn am_i()->bool {true}}

unsafe impl <T: Any> List for ListedType<T> {
  #[inline(always)]
  fn includes<U>()->bool {<T as AmI<U>>::am_i()}
}

macro_rules! tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> List for ($($T,)* $TL,)
      where $($T: List,)* $TL: List
    {
      #[inline(always)]
      fn includes<T>()->bool {
        $($T::includes::<T>() || )* $TL::includes::<T>()
      }
    }
    tuple_impls! ($($T),*);
  };
  () => {};
}

tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DeterministicallyRandomlyIdentifiedTypeId(u64);
pub trait DeterministicallyRandomlyIdentifiedType {
  const ID: DeterministicallyRandomlyIdentifiedTypeId;
}

fn assert_unique_global_list <GlobalList: List>() {
  use std::any::TypeId;
  use std::cell::Cell;
  thread_local! {
    static LIST_ID: Cell<Option <TypeId>> = Cell::new (None);
  }
  LIST_ID.with (| id_cell | {
    let id = TypeId::of::<GlobalList>();
    if let Some (existing) = id_cell.get() {
      assert!(id == existing, "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong");
      return
    }
    id_cell.set (Some(id));
  });
}

time_steward_make_sublist! (
mod whatever visits T where T: super::DeterministicallyRandomlyIdentifiedType);
/*
#[macro_export]
macro_rules! time_steward_sublist_fn {
  (static $visitor_data: ident: $VisitorData: ty: $VisitorTrait: ident = $initial_value: expr followed by visit<$T> (&mut $self_hack) $visitation_effect: expr; fn $function_name: ident <$GlobalList: $SubList: ident> ($($argument_name: ident: $argument_type:ty),*)->$return_type:ty $($body:tt)*) => {

    fn $function_name <GlobalList: $List> $($argument_name: $argument_type),*)->$return_type:ty {
      struct Visitor ($VisitorData);
      impl VisitorTrait for Visitor {
        fn visit<$T>(&mut $self_hack) where  {$visitation_effect}
      }
      thread_local! {
        static DATA: $VisitorData = {
          let mut visitor = Visitor ($initial_value);
          <GlobalList as DeterministicallyRandomlyIdentifiedTypesList>::visit_all (&mut visitor);
          visitor.0
        };
      }
      DATA.with (| $visitor_data | {$($body)*})
  }
}
  */

#[macro_export]
macro_rules! time_steward_visit_sublist {
  (&mut $object: ident: $Object: ty, <$GlobalList: ident as $mod: ident::SubList>, $($method: tt)*) => {
    impl $mod::Visitor for $Object {
      $($method)*
    }
    <$GlobalList as $mod::SubList>::visit_all (&mut $object);
  }
}
#[macro_export]
macro_rules! time_steward_with_sublist_table_entry {
  (<$GlobalList: ident as $mod: ident::SubList>, Vec<$Entry: ty> [$T: ident => {$entry: expr} where $($where: tt)*] [$index: expr], | $entry_variable: ident | $($closure: tt)*) => {{
    assert_unique_global_list::<$GlobalList>();
    use std::cell::RefCell;
    use std::mem;
    thread_local! {
      static TABLE: RefCell<Vec<DeterministicallyRandomlyIdentifiedTypeId>> = RefCell::new(Vec::new());
    }
    TABLE.with (| table | {
      let mut guard = table.borrow_mut();
      if guard.is_empty() {
        mem::replace (&mut*guard, {
          let mut result = Vec::with_capacity($mod::Representative::<$GlobalList>::count());
          time_steward_visit_sublist! (
            &mut result: Vec<$Entry>,
            <$GlobalList as $mod::SubList>,
            fn visit<$T>(&mut self) where $($where)* {self.push ($entry);}
          );
          result
        });
      }
      let $entry_variable = guard.get ($index.0);
      $($closure)*
    })
  }}
}

use std::any::Any ;

fn index_to_id <GlobalList: whatever::SubList> (index: ListedTypeIndex)->Option <DeterministicallyRandomlyIdentifiedTypeId> {
  time_steward_with_sublist_table_entry! (
    <GlobalList as whatever::SubList>,
    Vec<DeterministicallyRandomlyIdentifiedTypeId> [T => {T::ID} where T: DeterministicallyRandomlyIdentifiedType] [index],
    | entry | entry.cloned()
  )
}

#[macro_export]
macro_rules! time_steward_dynamic_sublist_fn {
  (fn $function_name: ident <GlobalList as $mod: ident::SubList> (index: ListedTypeIndex)->{$inner_function: ident::<Type(index)> ($($arguments: tt)*)->$Return:ty} where $($where: tt)*) => {
    fn $function_name <GlobalList: $mod::SubList> (index: ListedTypeIndex)->fn ($($arguments)*)->$Return {
      time_steward_with_sublist_table_entry! (
        <GlobalList as whatever::SubList>,
        Vec<DeterministicallyRandomlyIdentifiedTypeId> [T => {$inner_function::<T>} where $($where)*] [index],
        | entry | *entry.expect("invoked dynamic sublist fn with an invalid index")
      )
    }
  }
}

<commit_msg>More work on list of types system<commit_after>//! Allows dynamic dispatch to object-unsafe traits, with some caveats.
//!
//! `list_of_types` works around Rust's lack of generic/associated statics by requiring the program to specify a single "list of types" at compile time, which must include everything that you want to call into dynamically. This must be globally unique within the program. That is, if a *library* wants to use these features, it must rely on being passed the global list as a generic parameter.
//!
//! Creating a list of types is simple: you wrap each type `T` into `ListedType<T>`, then put the `ListedType`s into tuples (possibly nested tuples). All the traits necessary to use a list for automatically implemented for all nested tuples of `ListedType`s. For instance, ((ListedType<i64>, ListedType<String>, ListedType<Vec<usize>>), ListedType<bool>) is a valid list with 4 types in it.

use std::marker::PhantomData;

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ListedTypeIndex <Representative: SubListRepresentative> (usize, PhantomData <Representative>);

#[macro_export]
macro_rules! time_steward_make_sublist {
  (mod $mod: ident visits $T: ident where $($where:tt)*) => {mod $mod {
    use std::marker::PhantomData;
    use std::any::Any;
    use $crate::dynamic::list_of_types::{List, ListedType, SubListRepresentative, GlobalListConscious};
    pub trait Visitor {
      fn visit<$T>(&mut self) where $($where)*;
    }
    pub unsafe trait SubList: List {
      fn visit_all<V: Visitor>(visitor: &mut V);
      fn count()->usize;
      fn count_before<T>()->usize;
    }
    unsafe impl <T: Any> SubList for ListedType<T> {
      #[inline(always)]
      default fn visit_all<V: Visitor>(_: &mut V) {}
      #[inline(always)]
      default fn count()->usize {0}
      #[inline(always)]
      default fn count_before<U>()->usize {panic!("invoked count_before on a list that doesn't contain the type")}
    }
    unsafe impl <$T: Any> SubList for ListedType<$T> where $($where)* {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        visitor.visit::<$T>();
      }
      #[inline(always)]
      fn count()->usize {1}
      #[inline(always)]
      fn count_before<U>()->usize {0}
    }
    __time_steward_internal_sublist_tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

    pub struct Representative <GlobalList: SubList> (PhantomData <GlobalList>,!);
    impl <GlobalList: SubList> GlobalListConscious for Representative <GlobalList> {
      type GlobalList = GlobalList;
    }
    unsafe impl <GlobalList: SubList> SubListRepresentative for Representative <GlobalList> {
      fn count()->usize {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        GlobalList::count()
      }
      fn index <T>()->$crate::dynamic::list_of_types::ListedTypeIndex <Self> {
        $crate::dynamic::list_of_types::assert_unique_global_list::<GlobalList>();
        $crate::dynamic::list_of_types::ListedTypeIndex::<Self>(GlobalList::count_before::<T>(), PhantomData)
      }
    }/*{
      fn visit_all<V: Visitor>(visitor: &mut V) {
        GlobalList::visit_all(visitor);
      }
    }*/
  }}
}
pub struct ListedType<T: Any>(PhantomData <T>, !);

#[macro_export]
#[doc(hidden)]
macro_rules! __time_steward_internal_sublist_tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> SubList for ($($T,)* $TL,)
      where $($T: SubList,)* $TL: SubList
    {
      #[inline(always)]
      fn visit_all<V: Visitor>(visitor: &mut V) {
        // note: visiting order must be the same as the order of count_before()
        $($T::visit_all(visitor);)*
        $TL::visit_all(visitor);
      }
      #[inline(always)]
      fn count()->usize {
        $($T::count() + )* $TL::count()
      }
      #[inline(always)]
      fn count_before<T>()->usize {
        // note: visiting order must be the same as the order of count_before()
        let count = 0;
        $(if $T::includes::<T> () {return count + $T::count_before::<T>()}
        let count = count + $T::count();)*
        if $TL::includes::<T> () {return count + $TL::count_before::<T>()}
        panic!("invoked count_before on a list that doesn't contain the type")
      }
    }
    __time_steward_internal_sublist_tuple_impls! ($($T),*);
  };
  () => {};
}

pub unsafe trait List: Any {
  fn includes <T> ()->bool;
}
pub trait GlobalListConscious {
  type GlobalList: List;
}
pub unsafe trait SubListRepresentative: GlobalListConscious + Sized {
  fn count()->usize;
  fn index<T>()->ListedTypeIndex <Self>;
}

pub unsafe trait AmI <T> {fn am_i()->bool;}
unsafe impl <T, U> AmI <T> for U {default fn am_i()->bool {false}}
unsafe impl <T> AmI <T> for T {fn am_i()->bool {true}}

unsafe impl <T: Any> List for ListedType<T> {
  #[inline(always)]
  fn includes<U>()->bool {<T as AmI<U>>::am_i()}
}

macro_rules! tuple_impls {
  ($TL: ident $(, $T: ident)*) => {
    unsafe impl<$($T,)* $TL> List for ($($T,)* $TL,)
      where $($T: List,)* $TL: List
    {
      #[inline(always)]
      fn includes<T>()->bool {
        $($T::includes::<T>() || )* $TL::includes::<T>()
      }
    }
    tuple_impls! ($($T),*);
  };
  () => {};
}

tuple_impls! (T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, T21, T22, T23, T24, T25, T26, T27, T28, T29, T30, T31);

#[derive (Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct DeterministicallyRandomlyIdentifiedTypeId(u64);
pub trait DeterministicallyRandomlyIdentifiedType {
  const ID: DeterministicallyRandomlyIdentifiedTypeId;
}

fn assert_unique_global_list <GlobalList: List>() {
  use std::any::TypeId;
  use std::cell::Cell;
  thread_local! {
    static LIST_ID: Cell<Option <TypeId>> = Cell::new (None);
  }
  LIST_ID.with (| id_cell | {
    let id = TypeId::of::<GlobalList>();
    if let Some (existing) = id_cell.get() {
      assert!(id == existing, "invoked dynamic function with two different global lists (see the list_of_types documentation for why this is wrong");
      return
    }
    id_cell.set (Some(id));
  });
}

time_steward_make_sublist! (
mod whatever visits T where T: super::DeterministicallyRandomlyIdentifiedType);
/*
#[macro_export]
macro_rules! time_steward_sublist_fn {
  (static $visitor_data: ident: $VisitorData: ty: $VisitorTrait: ident = $initial_value: expr followed by visit<$T> (&mut $self_hack) $visitation_effect: expr; fn $function_name: ident <$GlobalList: $SubList: ident> ($($argument_name: ident: $argument_type:ty),*)->$return_type:ty $($body:tt)*) => {

    fn $function_name <GlobalList: $List> $($argument_name: $argument_type),*)->$return_type:ty {
      struct Visitor ($VisitorData);
      impl VisitorTrait for Visitor {
        fn visit<$T>(&mut $self_hack) where  {$visitation_effect}
      }
      thread_local! {
        static DATA: $VisitorData = {
          let mut visitor = Visitor ($initial_value);
          <GlobalList as DeterministicallyRandomlyIdentifiedTypesList>::visit_all (&mut visitor);
          visitor.0
        };
      }
      DATA.with (| $visitor_data | {$($body)*})
  }
}
  */

#[macro_export]
macro_rules! time_steward_visit_sublist {
  (&mut $object: ident: $Object: ty, $GlobalList: ident, [$($mod: tt)*], $($method: tt)*) => {
    impl $($mod)*::Visitor for $Object {
      $($method)*
    }
    <$GlobalList as $($mod)*::SubList>::visit_all (&mut $object);
  }
}
#[macro_export]
macro_rules! time_steward_with_sublist_table_entry {
  ($GlobalList: ident, [$($mod: tt)*], Vec<$Entry: ty> [$T: ident => {$entry: expr} where $($where: tt)*] [$index: expr], | $entry_variable: ident | $($closure: tt)*) => {{
    assert_unique_global_list::<$GlobalList>();
    use std::cell::RefCell;
    use std::mem;
    thread_local! {
      static TABLE: RefCell<Vec<DeterministicallyRandomlyIdentifiedTypeId>> = RefCell::new(Vec::new());
    }
    TABLE.with (| table | {
      let mut guard = table.borrow_mut();
      if guard.is_empty() {
        mem::replace (&mut*guard, {
          let mut result = Vec::with_capacity($($mod)*::Representative::<$GlobalList>::count());
          time_steward_visit_sublist! (
            &mut result: Vec<$Entry>,
            $GlobalList, [$($mod)*],
            fn visit<$T>(&mut self) where $($where)* {self.push ($entry);}
          );
          result
        });
      }
      let $entry_variable = guard.get ($index.0).expect("an invalid ListedTypeIndex exists");
      $($closure)*
    })
  }}
}

use std::any::Any ;

fn index_to_id <GlobalList: whatever::SubList> (index: ListedTypeIndex <whatever::Representative<GlobalList>>)->DeterministicallyRandomlyIdentifiedTypeId {
  time_steward_with_sublist_table_entry! (
    GlobalList, [whatever],
    Vec<DeterministicallyRandomlyIdentifiedTypeId> [T => {T::ID} where T: DeterministicallyRandomlyIdentifiedType] [index],
    | entry | *entry
  )
}

#[macro_export]
macro_rules! time_steward_dynamic_sublist_fn {
  (fn $function_name: ident, GlobalList, [$($mod: tt)*], (index: ListedTypeIndex <...>)->{$inner_function: ident::<Type(index)> ($($arguments: tt)*)->$Return:ty} where $($where: tt)*) => {
    fn $function_name <GlobalList: $($mod)*::SubList> (index: ListedTypeIndex <$($mod)*::Representative>)->fn ($($arguments)*)->$Return {
      time_steward_with_sublist_table_entry! (
        <GlobalList as whatever::SubList>,
        Vec<DeterministicallyRandomlyIdentifiedTypeId> [T => {$inner_function::<T>} where $($where)*] [index],
        | entry | *entry
      )
    }
  }
}

use serde::{Serialize, Deserialize, Serializer, Deserializer};

/*impl <Representative: SubListRepresentative> Serialize for ListedTypeIndex <Representative> {
  fn serialize <S: Serializer> (&self, serializer: S)->Result <S::Ok, S::Error> {
    index_to_id::<Representative::GlobalList> (*self).serialize (serializer);
  }
}*/

<|endoftext|>