<commit_before>// Determines the ways in which a generic function body depends
// on its type parameters. Used to aggressively reuse compiled
// function bodies for different types.

// This unfortunately depends on quite a bit of knowledge about the
// details of the language semantics, and is likely to accidentally go
// out of sync when something is changed. It could be made more
// powerful by distinguishing between functions that only need to know
// the size and alignment of a type, and those that also use its
// drop/take glue. But this would increase the fragility of the code
// to a ridiculous level, and probably not catch all that many extra
// opportunities for reuse.

// (An other approach to doing what this code does is to instrument
// the translation code to set flags whenever it does something like
// alloca a type or get a tydesc. This would not duplicate quite as
// much information, but have the disadvantage of being very
// invasive.)

import std::map::hashmap;
import std::list;
import std::list::{list, cons, nil};
import driver::session::session;
import metadata::csearch;
import syntax::ast::*, syntax::ast_util, syntax::visit;
import syntax::ast_map;
import common::*;

// FIXME distinguish between size/alignment and take/drop dependencies
type type_uses = uint; // Bitmask
const use_repr: uint = 1u; // Dependency on size/alignment and take/drop glue
const use_tydesc: uint = 2u; // Takes the tydesc, or compares

type ctx = {ccx: @crate_ctxt,
            uses: [mut type_uses]};

fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
    -> [type_uses] {
    alt ccx.type_use_cache.find(fn_id) {
      some(uses) { ret uses; }
      none {}
    }
    let fn_id_loc = if fn_id.crate == local_crate { fn_id }
                    else { base::maybe_instantiate_inline(ccx, fn_id) };
    // Conservatively assume full use for recursive loops
    ccx.type_use_cache.insert(fn_id, vec::from_elem(n_tps, 3u));

    let cx = {ccx: ccx, uses: vec::to_mut(vec::from_elem(n_tps, 0u))};
    alt ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).struct {
      ty::ty_fn({inputs, _}) {
        for vec::each(inputs) {|arg|
            if arg.mode == expl(by_val) { type_needs(cx, use_repr, arg.ty); }
        }
      }
      _ {}
    }

    if fn_id_loc.crate != local_crate {
        let uses = vec::from_mut(copy cx.uses);
        ccx.type_use_cache.insert(fn_id, uses);
        ret uses;
    }
    let map_node = alt ccx.tcx.items.find(fn_id_loc.node) {
        some(x) { x }
        none    { ccx.sess.bug(#fmt("type_uses_for: unbound item ID %?",
                                    fn_id_loc)); }
    };
    alt check map_node {
      ast_map::node_item(@{node: item_fn(_, _, body), _}, _) |
      ast_map::node_item(@{node: item_res(_, _, body, _, _, _), _}, _) |
      ast_map::node_method(@{body, _}, _, _) {
        handle_body(cx, body);
      }
      ast_map::node_ctor(_, _, ast_map::res_ctor(_, _, _), _) |
      ast_map::node_variant(_, _, _) {
        for uint::range(0u, n_tps) {|n| cx.uses[n] |= use_repr;}
      }
      ast_map::node_native_item(i@@{node: native_item_fn(_, _), _}, abi, _) {
        if abi == native_abi_rust_intrinsic {
            let flags = alt check i.ident {
              "visit_ty" { 3u }
              "size_of" |  "pref_align_of" | "min_align_of" |
              "init" |  "reinterpret_cast" { use_repr }
              "get_tydesc" | "needs_drop" { use_tydesc }
              "forget" | "addr_of" { 0u }
            };
            for uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;}
        }
      }
      ast_map::node_ctor(_, _, ast_map::class_ctor(ctor, _), _){
        handle_body(cx, ctor.node.body);
      }
      ast_map::node_dtor(_, dtor, _, _){
        handle_body(cx, dtor.node.body);
      }

    }
    let uses = vec::from_mut(copy cx.uses);
    ccx.type_use_cache.insert(fn_id, uses);
    uses
}

fn type_needs(cx: ctx, use: uint, ty: ty::t) {
    let mut done = true;
    // Optimization -- don't descend type if all params already have this use
    for vec::each(cx.uses) {|u| if u & use != use { done = false } }
    if !done { type_needs_inner(cx, use, ty, @nil); }
}

fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
                    enums_seen: @list<def_id>) {
    ty::maybe_walk_ty(ty) {|ty|
        if ty::type_has_params(ty) {
            alt ty::get(ty).struct {
              ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) |
              ty::ty_box(_) | ty::ty_iface(_, _) { false }
              ty::ty_enum(did, substs) {
                if option::is_none(list::find(enums_seen, {|id| id == did})) {
                    let seen = @cons(did, enums_seen);
                    for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v|
                        for vec::each(v.args) {|aty|
                            let t = ty::subst(cx.ccx.tcx, substs, aty);
                            type_needs_inner(cx, use, t, seen);
                        }
                    }
                }
                false
              }
              ty::ty_param(n, _) {
                cx.uses[n] |= use;
                false
              }
              _ { true }
            }
        } else { false }
    }
}

fn node_type_needs(cx: ctx, use: uint, id: node_id) {
    type_needs(cx, use, ty::node_id_to_type(cx.ccx.tcx, id));
}

fn mark_for_expr(cx: ctx, e: @expr) {
    alt e.node {
      expr_vstore(_, _) |
      expr_vec(_, _) |
      expr_rec(_, _) | expr_tup(_) |
      expr_unary(box(_), _) | expr_unary(uniq(_), _) |
      expr_cast(_, _) | expr_binary(add, _, _) |
      expr_copy(_) | expr_move(_, _) {
        node_type_needs(cx, use_repr, e.id);
      }
      expr_binary(op, lhs, _) {
        alt op {
          eq | lt | le | ne | ge | gt {
            node_type_needs(cx, use_tydesc, lhs.id)
          }
          _ {}
        }
      }
      expr_path(_) {
        cx.ccx.tcx.node_type_substs.find(e.id).iter {|ts|
            let id = ast_util::def_id_of_def(cx.ccx.tcx.def_map.get(e.id));
            vec::iter2(type_uses_for(cx.ccx, id, ts.len()), ts) {|uses, subst|
                type_needs(cx, uses, subst)
            }
        }
      }
      expr_fn(*) | expr_fn_block(*) {
        alt ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) {
          proto_bare | proto_any | proto_uniq {}
          proto_box | proto_block {
            for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) {|fv|
                let node_id = ast_util::def_id_of_def(fv.def).node;
                node_type_needs(cx, use_repr, node_id);
            }
          }
        }
      }
      expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) |
      expr_ret(some(val)) {
        node_type_needs(cx, use_repr, val.id);
      }
      expr_index(base, _) | expr_field(base, _, _) {
        // FIXME could be more careful and not count fields
        // after the chosen field (#2537)
        let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
        type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));

        option::iter(cx.ccx.maps.method_map.find(e.id)) {|mth|
            alt mth {
              typeck::method_static(did) {
                option::iter(cx.ccx.tcx.node_type_substs.find(e.id)) {|ts|
                    vec::iter2(type_uses_for(cx.ccx, did, ts.len()), ts)
                        {|uses, subst| type_needs(cx, uses, subst)}
                }
              }
              typeck::method_param(_, _, param, _) {
                cx.uses[param] |= use_tydesc;
              }
              typeck::method_iface(_, _) {}
            }
        }
      }
      expr_log(_, _, val) {
        node_type_needs(cx, use_tydesc, val.id);
      }
      expr_new(_, _, v) {
        node_type_needs(cx, use_repr, v.id);
      }
      expr_call(f, _, _) {
        vec::iter(ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, f.id))) {|a|
            alt a.mode {
              expl(by_move) | expl(by_copy) | expl(by_val) {
                type_needs(cx, use_repr, a.ty);
              }
              _ {}
            }
        }
      }
      expr_alt(_, _, _) | expr_block(_) | expr_if(_, _, _) |
      expr_while(_, _) | expr_fail(_) | expr_break | expr_cont |
      expr_unary(_, _) | expr_lit(_) | expr_assert(_) | expr_check(_, _) |
      expr_if_check(_, _, _) | expr_mac(_) | expr_addr_of(_, _) |
      expr_ret(_) | expr_loop(_) | expr_bind(_, _) | expr_loop_body(_) {}
    }
}

fn handle_body(cx: ctx, body: blk) {
    let v = visit::mk_vt(@{
        visit_expr: {|e, cx, v|
            visit::visit_expr(e, cx, v);
            mark_for_expr(cx, e);
        },
        visit_local: {|l, cx, v|
            visit::visit_local(l, cx, v);
            node_type_needs(cx, use_repr, l.node.id);
        },
        visit_pat: {|p, cx, v|
            visit::visit_pat(p, cx, v);
            node_type_needs(cx, use_repr, p.id);
        },
        visit_block: {|b, cx, v|
            visit::visit_block(b, cx, v);
            option::iter(b.node.expr) {|e|
                node_type_needs(cx, use_repr, e.id);
            }
        },
        visit_item: {|_i, _cx, _v|}
        with *visit::default_visitor()
    });
    v.visit_block(body, cx, v);
}
<commit_msg>Remove an irrelevant comment<commit_after>// Determines the ways in which a generic function body depends
// on its type parameters. Used to aggressively reuse compiled
// function bodies for different types.

// This unfortunately depends on quite a bit of knowledge about the
// details of the language semantics, and is likely to accidentally go
// out of sync when something is changed. It could be made more
// powerful by distinguishing between functions that only need to know
// the size and alignment of a type, and those that also use its
// drop/take glue. But this would increase the fragility of the code
// to a ridiculous level, and probably not catch all that many extra
// opportunities for reuse.

// (An other approach to doing what this code does is to instrument
// the translation code to set flags whenever it does something like
// alloca a type or get a tydesc. This would not duplicate quite as
// much information, but have the disadvantage of being very
// invasive.)

import std::map::hashmap;
import std::list;
import std::list::{list, cons, nil};
import driver::session::session;
import metadata::csearch;
import syntax::ast::*, syntax::ast_util, syntax::visit;
import syntax::ast_map;
import common::*;

type type_uses = uint; // Bitmask
const use_repr: uint = 1u; // Dependency on size/alignment and take/drop glue
const use_tydesc: uint = 2u; // Takes the tydesc, or compares

type ctx = {ccx: @crate_ctxt,
            uses: [mut type_uses]};

fn type_uses_for(ccx: @crate_ctxt, fn_id: def_id, n_tps: uint)
    -> [type_uses] {
    alt ccx.type_use_cache.find(fn_id) {
      some(uses) { ret uses; }
      none {}
    }
    let fn_id_loc = if fn_id.crate == local_crate { fn_id }
                    else { base::maybe_instantiate_inline(ccx, fn_id) };
    // Conservatively assume full use for recursive loops
    ccx.type_use_cache.insert(fn_id, vec::from_elem(n_tps, 3u));

    let cx = {ccx: ccx, uses: vec::to_mut(vec::from_elem(n_tps, 0u))};
    alt ty::get(ty::lookup_item_type(cx.ccx.tcx, fn_id).ty).struct {
      ty::ty_fn({inputs, _}) {
        for vec::each(inputs) {|arg|
            if arg.mode == expl(by_val) { type_needs(cx, use_repr, arg.ty); }
        }
      }
      _ {}
    }

    if fn_id_loc.crate != local_crate {
        let uses = vec::from_mut(copy cx.uses);
        ccx.type_use_cache.insert(fn_id, uses);
        ret uses;
    }
    let map_node = alt ccx.tcx.items.find(fn_id_loc.node) {
        some(x) { x }
        none    { ccx.sess.bug(#fmt("type_uses_for: unbound item ID %?",
                                    fn_id_loc)); }
    };
    alt check map_node {
      ast_map::node_item(@{node: item_fn(_, _, body), _}, _) |
      ast_map::node_item(@{node: item_res(_, _, body, _, _, _), _}, _) |
      ast_map::node_method(@{body, _}, _, _) {
        handle_body(cx, body);
      }
      ast_map::node_ctor(_, _, ast_map::res_ctor(_, _, _), _) |
      ast_map::node_variant(_, _, _) {
        for uint::range(0u, n_tps) {|n| cx.uses[n] |= use_repr;}
      }
      ast_map::node_native_item(i@@{node: native_item_fn(_, _), _}, abi, _) {
        if abi == native_abi_rust_intrinsic {
            let flags = alt check i.ident {
              "visit_ty" { 3u }
              "size_of" |  "pref_align_of" | "min_align_of" |
              "init" |  "reinterpret_cast" { use_repr }
              "get_tydesc" | "needs_drop" { use_tydesc }
              "forget" | "addr_of" { 0u }
            };
            for uint::range(0u, n_tps) {|n| cx.uses[n] |= flags;}
        }
      }
      ast_map::node_ctor(_, _, ast_map::class_ctor(ctor, _), _){
        handle_body(cx, ctor.node.body);
      }
      ast_map::node_dtor(_, dtor, _, _){
        handle_body(cx, dtor.node.body);
      }

    }
    let uses = vec::from_mut(copy cx.uses);
    ccx.type_use_cache.insert(fn_id, uses);
    uses
}

fn type_needs(cx: ctx, use: uint, ty: ty::t) {
    let mut done = true;
    // Optimization -- don't descend type if all params already have this use
    for vec::each(cx.uses) {|u| if u & use != use { done = false } }
    if !done { type_needs_inner(cx, use, ty, @nil); }
}

fn type_needs_inner(cx: ctx, use: uint, ty: ty::t,
                    enums_seen: @list<def_id>) {
    ty::maybe_walk_ty(ty) {|ty|
        if ty::type_has_params(ty) {
            alt ty::get(ty).struct {
              ty::ty_fn(_) | ty::ty_ptr(_) | ty::ty_rptr(_, _) |
              ty::ty_box(_) | ty::ty_iface(_, _) { false }
              ty::ty_enum(did, substs) {
                if option::is_none(list::find(enums_seen, {|id| id == did})) {
                    let seen = @cons(did, enums_seen);
                    for vec::each(*ty::enum_variants(cx.ccx.tcx, did)) {|v|
                        for vec::each(v.args) {|aty|
                            let t = ty::subst(cx.ccx.tcx, substs, aty);
                            type_needs_inner(cx, use, t, seen);
                        }
                    }
                }
                false
              }
              ty::ty_param(n, _) {
                cx.uses[n] |= use;
                false
              }
              _ { true }
            }
        } else { false }
    }
}

fn node_type_needs(cx: ctx, use: uint, id: node_id) {
    type_needs(cx, use, ty::node_id_to_type(cx.ccx.tcx, id));
}

fn mark_for_expr(cx: ctx, e: @expr) {
    alt e.node {
      expr_vstore(_, _) |
      expr_vec(_, _) |
      expr_rec(_, _) | expr_tup(_) |
      expr_unary(box(_), _) | expr_unary(uniq(_), _) |
      expr_cast(_, _) | expr_binary(add, _, _) |
      expr_copy(_) | expr_move(_, _) {
        node_type_needs(cx, use_repr, e.id);
      }
      expr_binary(op, lhs, _) {
        alt op {
          eq | lt | le | ne | ge | gt {
            node_type_needs(cx, use_tydesc, lhs.id)
          }
          _ {}
        }
      }
      expr_path(_) {
        cx.ccx.tcx.node_type_substs.find(e.id).iter {|ts|
            let id = ast_util::def_id_of_def(cx.ccx.tcx.def_map.get(e.id));
            vec::iter2(type_uses_for(cx.ccx, id, ts.len()), ts) {|uses, subst|
                type_needs(cx, uses, subst)
            }
        }
      }
      expr_fn(*) | expr_fn_block(*) {
        alt ty::ty_fn_proto(ty::expr_ty(cx.ccx.tcx, e)) {
          proto_bare | proto_any | proto_uniq {}
          proto_box | proto_block {
            for vec::each(*freevars::get_freevars(cx.ccx.tcx, e.id)) {|fv|
                let node_id = ast_util::def_id_of_def(fv.def).node;
                node_type_needs(cx, use_repr, node_id);
            }
          }
        }
      }
      expr_assign(val, _) | expr_swap(val, _) | expr_assign_op(_, val, _) |
      expr_ret(some(val)) {
        node_type_needs(cx, use_repr, val.id);
      }
      expr_index(base, _) | expr_field(base, _, _) {
        // FIXME could be more careful and not count fields
        // after the chosen field (#2537)
        let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
        type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));

        option::iter(cx.ccx.maps.method_map.find(e.id)) {|mth|
            alt mth {
              typeck::method_static(did) {
                option::iter(cx.ccx.tcx.node_type_substs.find(e.id)) {|ts|
                    vec::iter2(type_uses_for(cx.ccx, did, ts.len()), ts)
                        {|uses, subst| type_needs(cx, uses, subst)}
                }
              }
              typeck::method_param(_, _, param, _) {
                cx.uses[param] |= use_tydesc;
              }
              typeck::method_iface(_, _) {}
            }
        }
      }
      expr_log(_, _, val) {
        node_type_needs(cx, use_tydesc, val.id);
      }
      expr_new(_, _, v) {
        node_type_needs(cx, use_repr, v.id);
      }
      expr_call(f, _, _) {
        vec::iter(ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx, f.id))) {|a|
            alt a.mode {
              expl(by_move) | expl(by_copy) | expl(by_val) {
                type_needs(cx, use_repr, a.ty);
              }
              _ {}
            }
        }
      }
      expr_alt(_, _, _) | expr_block(_) | expr_if(_, _, _) |
      expr_while(_, _) | expr_fail(_) | expr_break | expr_cont |
      expr_unary(_, _) | expr_lit(_) | expr_assert(_) | expr_check(_, _) |
      expr_if_check(_, _, _) | expr_mac(_) | expr_addr_of(_, _) |
      expr_ret(_) | expr_loop(_) | expr_bind(_, _) | expr_loop_body(_) {}
    }
}

fn handle_body(cx: ctx, body: blk) {
    let v = visit::mk_vt(@{
        visit_expr: {|e, cx, v|
            visit::visit_expr(e, cx, v);
            mark_for_expr(cx, e);
        },
        visit_local: {|l, cx, v|
            visit::visit_local(l, cx, v);
            node_type_needs(cx, use_repr, l.node.id);
        },
        visit_pat: {|p, cx, v|
            visit::visit_pat(p, cx, v);
            node_type_needs(cx, use_repr, p.id);
        },
        visit_block: {|b, cx, v|
            visit::visit_block(b, cx, v);
            option::iter(b.node.expr) {|e|
                node_type_needs(cx, use_repr, e.id);
            }
        },
        visit_item: {|_i, _cx, _v|}
        with *visit::default_visitor()
    });
    v.visit_block(body, cx, v);
}
<|endoftext|>


<commit_before>fn main() {
    auto x = @mutable 5;
    *x = 1000;
    log *x;
}

<commit_msg>Fix effect on deref-lval<commit_after>impure fn main() {
    auto x = @mutable 5;
    *x = 1000;
    log *x;
}

<|endoftext|>


<commit_before>use crate::model::prelude::*;

/// Information about a guild scheduled event.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScheduledEvent {
    /// The Id of the scheduled event.
    pub id: ScheduledEventId,
    /// The Id of the guild that the event belongs to.
    pub guild_id: GuildId,
    /// The Id of the channel that the event belongs to, if any.
    pub channel_id: Option<ChannelId>,
    /// The Id of the User that created the scheduled event.
    ///
    /// Only `None` for events created before October 25th, 2021.
    pub creator_id: Option<UserId>,
    /// The name of the scheduled event.
    pub name: String,
    /// The description of the scheduled event, if any.
    pub description: Option<String>,
    /// The event's starting time.
    #[serde(rename = "scheduled_start_time")]
    pub start_time: Timestamp,
    /// The event's ending time; optional.
    #[serde(rename = "scheduled_end_time")]
    pub end_time: Option<Timestamp>,
    /// The event's status; either Scheduled, Active, Completed, or Canceled.
    pub status: ScheduledEventStatus,
    /// The User that created the event.
    ///
    /// Only `None` for events created before October 25th, 2021.
    pub creator: Option<User>,
    /// The type of the event, indicating if it will take place in a Stage Instance, a Voice
    /// Channel, or at some External location.
    #[serde(rename = "entity_type")]
    pub kind: ScheduledEventType,
    /// Optional event location, only required for External events.
    #[serde(rename = "entity_metadata")]
    pub metadata: Option<ScheduledEventMetadata>,
    /// Number of users interested in the event.
    ///
    /// Only populated if `with_user_count` is set to true provided when calling
    /// [`GuildId::scheduled_event`] or [`GuildId::scheduled_events`].
    pub user_count: Option<u64>,
    /// The hash of the event's cover image, if present.
    pub image: Option<String>,
}

#[derive(Copy, Clone, Debug)]
pub enum ScheduledEventStatus {
    Scheduled = 1,
    Active = 2,
    Completed = 3,
    Canceled = 4,
    Unknown = !0,
}

enum_number!(ScheduledEventStatus {
    Scheduled,
    Active,
    Completed,
    Canceled,
});

#[derive(Copy, Clone, Debug)]
pub enum ScheduledEventType {
    StageInstance = 1,
    Voice = 2,
    External = 3,
    Unknown = !0,
}

enum_number!(ScheduledEventType {
    StageInstance,
    Voice,
    External,
});

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ScheduledEventMetadata {
    pub location: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ScheduledEventUser {
    #[serde(rename = "guild_scheduled_event_id")]
    pub event_id: ScheduledEventId,
    pub user: User,
    pub member: Option<Member>,
}
<commit_msg>Use `#[serde(default)]` for the `ScheduledEventMetadata::location` field (#1916)<commit_after>use crate::model::prelude::*;

/// Information about a guild scheduled event.
#[derive(Clone, Debug, Serialize, Deserialize)]
#[non_exhaustive]
pub struct ScheduledEvent {
    /// The Id of the scheduled event.
    pub id: ScheduledEventId,
    /// The Id of the guild that the event belongs to.
    pub guild_id: GuildId,
    /// The Id of the channel that the event belongs to, if any.
    pub channel_id: Option<ChannelId>,
    /// The Id of the User that created the scheduled event.
    ///
    /// Only `None` for events created before October 25th, 2021.
    pub creator_id: Option<UserId>,
    /// The name of the scheduled event.
    pub name: String,
    /// The description of the scheduled event, if any.
    pub description: Option<String>,
    /// The event's starting time.
    #[serde(rename = "scheduled_start_time")]
    pub start_time: Timestamp,
    /// The event's ending time; optional.
    #[serde(rename = "scheduled_end_time")]
    pub end_time: Option<Timestamp>,
    /// The event's status; either Scheduled, Active, Completed, or Canceled.
    pub status: ScheduledEventStatus,
    /// The User that created the event.
    ///
    /// Only `None` for events created before October 25th, 2021.
    pub creator: Option<User>,
    /// The type of the event, indicating if it will take place in a Stage Instance, a Voice
    /// Channel, or at some External location.
    #[serde(rename = "entity_type")]
    pub kind: ScheduledEventType,
    /// Optional event location, only required for External events.
    #[serde(rename = "entity_metadata")]
    pub metadata: Option<ScheduledEventMetadata>,
    /// Number of users interested in the event.
    ///
    /// Only populated if `with_user_count` is set to true provided when calling
    /// [`GuildId::scheduled_event`] or [`GuildId::scheduled_events`].
    pub user_count: Option<u64>,
    /// The hash of the event's cover image, if present.
    pub image: Option<String>,
}

#[derive(Copy, Clone, Debug)]
pub enum ScheduledEventStatus {
    Scheduled = 1,
    Active = 2,
    Completed = 3,
    Canceled = 4,
    Unknown = !0,
}

enum_number!(ScheduledEventStatus {
    Scheduled,
    Active,
    Completed,
    Canceled,
});

#[derive(Copy, Clone, Debug)]
pub enum ScheduledEventType {
    StageInstance = 1,
    Voice = 2,
    External = 3,
    Unknown = !0,
}

enum_number!(ScheduledEventType {
    StageInstance,
    Voice,
    External,
});

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ScheduledEventMetadata {
    // TODO: Change to `Option<String>` in next version.
    #[serde(default)]
    pub location: String,
}

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct ScheduledEventUser {
    #[serde(rename = "guild_scheduled_event_id")]
    pub event_id: ScheduledEventId,
    pub user: User,
    pub member: Option<Member>,
}
<|endoftext|>


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

use std::io::{Read, Write};
use std::io::Result as IoResult;
use std::net::{SocketAddr, TcpStream, Shutdown};

#[cfg(feature = "ssl")]
use openssl::ssl::SslStream;

pub struct RefinedTcpStream {
    stream: Stream,
    close_read: bool,
    close_write: bool,
}

enum Stream {
    Http(TcpStream),
    #[cfg(feature = "ssl")]
    Https(SslStream<TcpStream>),
}

impl RefinedTcpStream {
    pub fn new(stream: TcpStream) -> (RefinedTcpStream, RefinedTcpStream) {
        let read = stream.try_clone().unwrap();
        let read = RefinedTcpStream {
            stream: Stream::Http(read),
            close_read: true,
            close_write: false,
        };

        let write = RefinedTcpStream {
            stream: Stream::Http(stream),
            close_read: false,
            close_write: true,
        };

        (read, write)
    }

    pub fn peer_addr(&mut self) -> IoResult<SocketAddr> {
        match self.stream {
            Stream::Http(ref mut stream) => stream.peer_addr(),
            #[cfg(feature = "ssl")]
            Stream::Https(ref mut stream) => stream.get_ref().peer_addr(),
        }
    }
}

impl Drop for RefinedTcpStream {
    fn drop(&mut self) {
        if self.close_read {
            match self.stream {
                // ignoring outcome
                Stream::Http(ref mut stream) => stream.shutdown(Shutdown::Read).ok(),
                #[cfg(feature = "ssl")]
                Stream::Https(ref mut stream) => stream.get_mut().shutdown(Shutdown::Read).ok(),
            };
        }

        if self.close_write {
            match self.stream {
                // ignoring outcome
                Stream::Http(ref mut stream) => stream.shutdown(Shutdown::Write).ok(),
                #[cfg(feature = "ssl")]
                Stream::Https(ref mut stream) => stream.get_mut().shutdown(Shutdown::Write).ok(),
            };
        }
    }
}

impl Read for RefinedTcpStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        match self.stream {
            Stream::Http(ref mut stream) => stream.read(buf),
            #[cfg(feature = "ssl")]
            Stream::Https(ref mut stream) => stream.read(buf),
        }
    }
}

impl Write for RefinedTcpStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
        match self.stream {
            Stream::Http(ref mut stream) => stream.write(buf),
            #[cfg(feature = "ssl")]
            Stream::Https(ref mut stream) => stream.write(buf),
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match self.stream {
            Stream::Http(ref mut stream) => stream.flush(),
            #[cfg(feature = "ssl")]
            Stream::Https(ref mut stream) => stream.flush(),
        }
    }
}
<commit_msg>RefinedTcpStream::new now takes Into<Stream><commit_after>// Copyright 2015 The tiny-http Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::io::{Read, Write};
use std::io::Result as IoResult;
use std::net::{SocketAddr, TcpStream, Shutdown};

#[cfg(feature = "ssl")]
use openssl::ssl::SslStream;

pub struct RefinedTcpStream {
    stream: Stream,
    close_read: bool,
    close_write: bool,
}

enum Stream {
    Http(TcpStream),
    #[cfg(feature = "ssl")]
    Https(SslStream<TcpStream>),
}

impl From<TcpStream> for Stream {
    #[inline]
    fn from(stream: TcpStream) -> Stream {
        Stream::Http(stream)
    }
}

#[cfg(feature = "ssl")]
impl From<SslStream<TcpStream>> for Stream {
    #[inline]
    fn from(stream: SslStream<TcpStream>) -> Stream {
        Stream::Https(stream)
    }
}

impl RefinedTcpStream {
    pub fn new<S>(stream: S) -> (RefinedTcpStream, RefinedTcpStream)
        where S: Into<Stream>
    {
        let stream = stream.into();

        let read = match stream {
            Stream::Http(ref stream) => Stream::Http(stream.try_clone().unwrap()),
            #[cfg(feature = "ssl")]
            Stream::Https(ref stream) => Stream::Https(stream.try_clone().unwrap()),
        };

        let read = RefinedTcpStream {
            stream: read,
            close_read: true,
            close_write: false,
        };

        let write = RefinedTcpStream {
            stream: stream,
            close_read: false,
            close_write: true,
        };

        (read, write)
    }

    pub fn peer_addr(&mut self) -> IoResult<SocketAddr> {
        match self.stream {
            Stream::Http(ref mut stream) => stream.peer_addr(),
            #[cfg(feature = "ssl")]
            Stream::Https(ref mut stream) => stream.get_ref().peer_addr(),
        }
    }
}

impl Drop for RefinedTcpStream {
    fn drop(&mut self) {
        if self.close_read {
            match self.stream {
                // ignoring outcome
                Stream::Http(ref mut stream) => stream.shutdown(Shutdown::Read).ok(),
                #[cfg(feature = "ssl")]
                Stream::Https(ref mut stream) => stream.get_mut().shutdown(Shutdown::Read).ok(),
            };
        }

        if self.close_write {
            match self.stream {
                // ignoring outcome
                Stream::Http(ref mut stream) => stream.shutdown(Shutdown::Write).ok(),
                #[cfg(feature = "ssl")]
                Stream::Https(ref mut stream) => stream.get_mut().shutdown(Shutdown::Write).ok(),
            };
        }
    }
}

impl Read for RefinedTcpStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        match self.stream {
            Stream::Http(ref mut stream) => stream.read(buf),
            #[cfg(feature = "ssl")]
            Stream::Https(ref mut stream) => stream.read(buf),
        }
    }
}

impl Write for RefinedTcpStream {
    fn write(&mut self, buf: &[u8]) -> IoResult<usize> {
        match self.stream {
            Stream::Http(ref mut stream) => stream.write(buf),
            #[cfg(feature = "ssl")]
            Stream::Https(ref mut stream) => stream.write(buf),
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match self.stream {
            Stream::Http(ref mut stream) => stream.flush(),
            #[cfg(feature = "ssl")]
            Stream::Https(ref mut stream) => stream.flush(),
        }
    }
}
<|endoftext|>


<commit_before>use std::path::Path;

use serde::{
    Deserialize,
    Serialize,
};

use itertools::Itertools;

use anyhow::Result;

use sorted_iter::{
    assume::*,
    SortedPairIterator,
};

use rnc_core::psql::JsonlIterator;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Accession {
    urs_taxid: String,
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<String>,
    all_common_names: Vec<String>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct RfamHit {
    urs_taxid: String,
    rfam_hit_id: usize,
    model: String,
    model_rna_type: Option<String>,
    model_domain: Option<String>,
    model_name: String,
    model_long_name: String,
    model_completeness: f64,
    model_start: usize,
    model_stop: usize,
    sequence_completeness: f64,
    sequence_start: usize,
    sequence_stop: usize,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct R2dtHit {
    urs_taxid: String,
    model_id: String,
    model_name: String,
    model_source: String,
    model_so_term: Option<String>,
    sequence_coverage: Option<f64>,
    model_coverage: Option<f64>,
    sequence_basepairs: Option<usize>,
    model_basepairs: Option<usize>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct Previous {
    urs_taxid: String,
    upi: String,
    taxid: usize,
    databases: String,
    description: Option<String>,
    has_coordinates: bool,
    is_active: bool,
    is_fragment: bool,
    is_locus_representative: bool,
    last_release: usize,
    rfam_problems: String,
    rna_type: String,
    short_description: Option<String>,
    so_rna_type: Option<String>,
    update_date: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RawAccessionEntry {
    urs_taxid: String,
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<Option<String>>,
    all_common_names: Vec<Option<String>>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Coordinate {
    urs_taxid: String,
    assembly_id: String,
    chromosome: String,
    strand: String,
    start: usize,
    stop: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Xref {
    urs_taxid: String,
    length: usize,
    deleted: String,
    last_release: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Metadata {
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    deleted: bool,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Normalized {
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    accessions: Vec<Accession>,
    deleted: bool,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

impl From<RawAccessionEntry> for Accession {
    fn from(raw: RawAccessionEntry) -> Self {
        return Self {
            urs_taxid: raw.urs_taxid,
            accession: raw.accession,
            is_active: raw.is_active,
            description: raw.description,
            gene: raw.gene,
            optional_id: raw.optional_id,
            database: raw.database,
            species: raw.species,
            common_name: raw.common_name,
            feature_name: raw.feature_name,
            ncrna_class: raw.ncrna_class,
            locus_tag: raw.locus_tag,
            organelle: raw.organelle,
            lineage: raw.lineage,
            all_species: raw.all_species.into_iter().filter_map(|s| s).collect(),
            all_common_names: raw.all_common_names.into_iter().filter_map(|s| s).collect(),
            so_rna_type: raw.so_rna_type,
        };
    }
}

impl Normalized {
    fn new(
        urs_taxid: String,
        raw_accessions: impl Iterator<Item = RawAccessionEntry>,
        raw_xrefs: impl Iterator<Item = Xref>,
        raw_coordinates: Option<impl Iterator<Item = Coordinate>>,
        raw_rfam_hits: Option<impl Iterator<Item = RfamHit>>,
        raw_r2dt_hits: Option<impl Iterator<Item = R2dtHit>>,
        raw_previous: Option<impl Iterator<Item = Previous>>,
    ) -> Result<Self> {
        let parts: Vec<&str> = urs_taxid.split("_").collect();
        let upi = parts[0].to_owned();
        let taxid = parts[1].parse::<usize>().unwrap();

        let xrefs: Vec<Xref> = raw_xrefs.collect();

        let coordinates = raw_coordinates.into_iter().flatten().collect();
        let rfam_hits = raw_rfam_hits.into_iter().flatten().collect();
        let r2dt_hits = raw_r2dt_hits.into_iter().flatten().collect();
        let previous: Vec<Previous> = raw_previous.into_iter().flatten().collect();
        let previous = match previous.len() {
            0 => None,
            _ => Some(previous[0].clone()),
        };

        let length = xrefs[0].length;
        let last_release = xrefs.iter().map(|x| x.last_release).max().unwrap();

        let mut deleted = true;
        let mut accessions = Vec::with_capacity(xrefs.len());
        for raw_accession in raw_accessions {
            if raw_accession.is_active {
                deleted = false;
            }
            accessions.push(Accession::from(raw_accession));
        }

        return Ok(Self {
            upi,
            taxid,
            length,
            last_release,
            coordinates,
            accessions,
            deleted,
            previous,
            rfam_hits,
            r2dt_hits,
        });
    }
}

impl Metadata {
    fn new(
        urs_taxid: String,
        raw_xrefs: impl Iterator<Item = Xref>,
        raw_coordinates: Option<impl Iterator<Item = Coordinate>>,
        raw_rfam_hits: Option<impl Iterator<Item = RfamHit>>,
        raw_r2dt_hits: Option<impl Iterator<Item = R2dtHit>>,
        raw_previous: Option<impl Iterator<Item = Previous>>,
    ) -> Result<Self> {
        let parts: Vec<&str> = urs_taxid.split("_").collect();
        let upi = parts[0].to_owned();
        let taxid = parts[1].parse::<usize>().unwrap();

        let xrefs: Vec<Xref> = raw_xrefs.collect();

        let coordinates = raw_coordinates.into_iter().flatten().collect();
        let rfam_hits = raw_rfam_hits.into_iter().flatten().collect();
        let r2dt_hits = raw_r2dt_hits.into_iter().flatten().collect();
        let previous: Vec<Previous> = raw_previous.into_iter().flatten().collect();
        let previous = match previous.len() {
            0 => None,
            _ => Some(previous[0].clone()),
        };

        let length = xrefs[0].length;
        let last_release = xrefs.iter().map(|x| x.last_release).max().unwrap();

        let deleted = xrefs.iter().all(|x| x.deleted == "Y");

        return Ok(Self {
            upi,
            taxid,
            length,
            last_release,
            coordinates,
            deleted,
            previous,
            rfam_hits,
            r2dt_hits,
        });
    }
}

pub fn write_metadata(
    coordinate_file: &Path,
    rfam_hits_file: &Path,
    r2dt_hits_file: &Path,
    previous_file: &Path,
    xref_file: &Path,
    output: &Path,
) -> Result<()> {
    let xrefs = JsonlIterator::from_path(xref_file)?;
    let xrefs = xrefs.group_by(|x: &Xref| x.urs_taxid.to_owned());
    let xrefs = xrefs.into_iter().assume_sorted_by_key();

    let coordinates = JsonlIterator::from_path(coordinate_file)?;
    let coordinates = coordinates.group_by(|c: &Coordinate| c.urs_taxid.to_owned());
    let coordinates = coordinates.into_iter().assume_sorted_by_key();

    let rfam_hits = JsonlIterator::from_path(rfam_hits_file)?;
    let rfam_hits = rfam_hits.group_by(|h: &RfamHit| h.urs_taxid.to_owned());
    let rfam_hits = rfam_hits.into_iter().assume_sorted_by_key();

    let r2dt_hits = JsonlIterator::from_path(r2dt_hits_file)?;
    let r2dt_hits = r2dt_hits.group_by(|h: &R2dtHit| h.urs_taxid.to_owned());
    let r2dt_hits = r2dt_hits.into_iter().assume_sorted_by_key();

    let previous = JsonlIterator::from_path(previous_file)?;
    let previous = previous.group_by(|p: &Previous| p.urs_taxid.to_owned());
    let previous = previous.into_iter().assume_sorted_by_key();

    let partial =
        xrefs.left_join(coordinates).left_join(rfam_hits).left_join(r2dt_hits).left_join(previous);

    let mut output = rnc_utils::buf_writer(output)?;
    for (id, data) in partial {
        let ((((xrefs, coordinates), rfam_hits), r2dt_hits), previous) = data;
        let norm = Metadata::new(id, xrefs, coordinates, rfam_hits, r2dt_hits, previous)?;
        serde_json::to_writer(&mut output, &norm)?;
        writeln!(&mut output)?;
    }

    Ok(())
}

pub fn write(
    accession_file: &Path,
    coordinate_file: &Path,
    rfam_hits_file: &Path,
    r2dt_hits_file: &Path,
    previous_file: &Path,
    xref_file: &Path,
    output: &Path,
) -> Result<()> {
    let accessions = JsonlIterator::from_path(accession_file)?;
    let accessions = accessions.group_by(|a: &RawAccessionEntry| a.urs_taxid.to_owned());
    let accessions = accessions.into_iter().assume_sorted_by_key();

    let xrefs = JsonlIterator::from_path(xref_file)?;
    let xrefs = xrefs.group_by(|x: &Xref| x.urs_taxid.to_owned());
    let xrefs = xrefs.into_iter().assume_sorted_by_key();

    let coordinates = JsonlIterator::from_path(coordinate_file)?;
    let coordinates = coordinates.group_by(|c: &Coordinate| c.urs_taxid.to_owned());
    let coordinates = coordinates.into_iter().assume_sorted_by_key();

    let rfam_hits = JsonlIterator::from_path(rfam_hits_file)?;
    let rfam_hits = rfam_hits.group_by(|h: &RfamHit| h.urs_taxid.to_owned());
    let rfam_hits = rfam_hits.into_iter().assume_sorted_by_key();

    let r2dt_hits = JsonlIterator::from_path(r2dt_hits_file)?;
    let r2dt_hits = r2dt_hits.group_by(|h: &R2dtHit| h.urs_taxid.to_owned());
    let r2dt_hits = r2dt_hits.into_iter().assume_sorted_by_key();

    let previous = JsonlIterator::from_path(previous_file)?;
    let previous = previous.group_by(|p: &Previous| p.urs_taxid.to_owned());
    let previous = previous.into_iter().assume_sorted_by_key();

    let partial = accessions
        .join(xrefs)
        .left_join(coordinates)
        .left_join(rfam_hits)
        .left_join(r2dt_hits)
        .left_join(previous);

    let mut output = rnc_utils::buf_writer(output)?;
    for (id, data) in partial {
        let (((((accessions, xrefs), coordinates), rfam_hits), r2dt_hits), previous) = data;
        let norm =
            Normalized::new(id, accessions, xrefs, coordinates, rfam_hits, r2dt_hits, previous)?;
        serde_json::to_writer(&mut output, &norm)?;
        writeln!(&mut output)?;
    }

    Ok(())
}
<commit_msg>Various bug fixes<commit_after>use std::path::Path;

use serde::{
    Deserialize,
    Serialize,
};

use itertools::Itertools;

use anyhow::Result;

use sorted_iter::{
    assume::*,
    SortedPairIterator,
};

use rnc_core::psql::JsonlIterator;

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Accession {
    urs_taxid: String,
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<String>,
    all_common_names: Vec<String>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct RfamHit {
    #[serde(rename = "id")]
    urs_taxid: String,
    rfam_hit_id: usize,
    model: String,
    model_rna_type: Option<String>,
    model_domain: Option<String>,
    model_name: String,
    model_long_name: String,
    model_completeness: f64,
    model_start: usize,
    model_stop: usize,
    sequence_completeness: f64,
    sequence_start: usize,
    sequence_stop: usize,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct R2dtHit {
    #[serde(rename = "id")]
    urs_taxid: String,
    model_id: usize,
    model_name: String,
    model_source: String,
    model_so_term: Option<String>,
    sequence_coverage: Option<f64>,
    model_coverage: Option<f64>,
    sequence_basepairs: Option<usize>,
    model_basepairs: Option<usize>,
}

#[derive(Clone, Debug, Deserialize, Serialize, PartialEq)]
pub struct Previous {
    #[serde(rename = "id")]
    urs_taxid: String,
    upi: String,
    taxid: usize,
    databases: Option<String>,
    description: Option<String>,
    has_coordinates: Option<bool>,
    is_active: Option<bool>,
    is_fragment: Option<bool>,
    is_locus_representative: Option<bool>,
    last_release: Option<usize>,
    rfam_problems: Option<String>,
    rna_type: Option<String>,
    short_description: Option<String>,
    so_rna_type: Option<String>,
    update_date: Option<String>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct RawAccessionEntry {
    urs_taxid: String,
    accession: String,
    is_active: bool,
    description: String,
    gene: Option<String>,
    optional_id: Option<String>,
    database: String,
    species: Option<String>,
    common_name: Option<String>,
    feature_name: Option<String>,
    ncrna_class: Option<String>,
    locus_tag: Option<String>,
    organelle: Option<String>,
    lineage: Option<String>,
    all_species: Vec<Option<String>>,
    all_common_names: Vec<Option<String>>,
    so_rna_type: Option<String>,
}

#[derive(Debug, Deserialize, Serialize, PartialEq)]
pub struct Coordinate {
    #[serde(rename = "id")]
    urs_taxid: String,
    assembly_id: String,
    chromosome: String,
    strand: i8,
    start: usize,
    stop: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Xref {
    #[serde(rename = "id")]
    urs_taxid: String,
    length: usize,
    deleted: String,
    last_release: usize,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Metadata {
    urs_taxid: String,
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    deleted: bool,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

#[derive(Debug, Deserialize, Serialize)]
pub struct Normalized {
    upi: String,
    taxid: usize,
    length: usize,
    last_release: usize,
    coordinates: Vec<Coordinate>,
    accessions: Vec<Accession>,
    deleted: bool,
    previous: Option<Previous>,
    rfam_hits: Vec<RfamHit>,
    r2dt_hits: Vec<R2dtHit>,
}

impl From<RawAccessionEntry> for Accession {
    fn from(raw: RawAccessionEntry) -> Self {
        return Self {
            urs_taxid: raw.urs_taxid,
            accession: raw.accession,
            is_active: raw.is_active,
            description: raw.description,
            gene: raw.gene,
            optional_id: raw.optional_id,
            database: raw.database,
            species: raw.species,
            common_name: raw.common_name,
            feature_name: raw.feature_name,
            ncrna_class: raw.ncrna_class,
            locus_tag: raw.locus_tag,
            organelle: raw.organelle,
            lineage: raw.lineage,
            all_species: raw.all_species.into_iter().filter_map(|s| s).collect(),
            all_common_names: raw.all_common_names.into_iter().filter_map(|s| s).collect(),
            so_rna_type: raw.so_rna_type,
        };
    }
}

impl Normalized {
    fn new(
        urs_taxid: String,
        raw_accessions: impl Iterator<Item = RawAccessionEntry>,
        raw_xrefs: impl Iterator<Item = Xref>,
        raw_coordinates: Option<impl Iterator<Item = Coordinate>>,
        raw_rfam_hits: Option<impl Iterator<Item = RfamHit>>,
        raw_r2dt_hits: Option<impl Iterator<Item = R2dtHit>>,
        raw_previous: Option<impl Iterator<Item = Previous>>,
    ) -> Result<Self> {
        let parts: Vec<&str> = urs_taxid.split("_").collect();
        let upi = parts[0].to_owned();
        let taxid = parts[1].parse::<usize>().unwrap();

        let xrefs: Vec<Xref> = raw_xrefs.collect();

        let coordinates = raw_coordinates.into_iter().flatten().collect();
        let rfam_hits = raw_rfam_hits.into_iter().flatten().collect();
        let r2dt_hits = raw_r2dt_hits.into_iter().flatten().collect();
        let previous: Vec<Previous> = raw_previous.into_iter().flatten().collect();
        let previous = match previous.len() {
            0 => None,
            _ => Some(previous[0].clone()),
        };

        let length = xrefs[0].length;
        let last_release = xrefs.iter().map(|x| x.last_release).max().unwrap();

        let mut deleted = true;
        let mut accessions = Vec::with_capacity(xrefs.len());
        for raw_accession in raw_accessions {
            if raw_accession.is_active {
                deleted = false;
            }
            accessions.push(Accession::from(raw_accession));
        }

        return Ok(Self {
            upi,
            taxid,
            length,
            last_release,
            coordinates,
            accessions,
            deleted,
            previous,
            rfam_hits,
            r2dt_hits,
        });
    }
}

impl Metadata {
    fn new(
        urs_taxid: String,
        raw_xrefs: impl Iterator<Item = Xref>,
        raw_coordinates: Option<impl Iterator<Item = Coordinate>>,
        raw_rfam_hits: Option<impl Iterator<Item = RfamHit>>,
        raw_r2dt_hits: Option<impl Iterator<Item = R2dtHit>>,
        raw_previous: Option<impl Iterator<Item = Previous>>,
    ) -> Result<Self> {
        let parts: Vec<&str> = urs_taxid.split("_").collect();
        let upi = parts[0].to_owned();
        let taxid = parts[1].parse::<usize>().unwrap();

        let xrefs: Vec<Xref> = raw_xrefs.collect();

        let coordinates = raw_coordinates.into_iter().flatten().collect();
        let rfam_hits = raw_rfam_hits.into_iter().flatten().collect();
        let r2dt_hits = raw_r2dt_hits.into_iter().flatten().collect();
        let previous: Vec<Previous> = raw_previous.into_iter().flatten().collect();
        let previous = match previous.len() {
            0 => None,
            _ => Some(previous[0].clone()),
        };

        let length = xrefs[0].length;
        let last_release = xrefs.iter().map(|x| x.last_release).max().unwrap();

        let deleted = xrefs.iter().all(|x| x.deleted == "Y");

        return Ok(Self {
            urs_taxid,
            upi,
            taxid,
            length,
            last_release,
            coordinates,
            deleted,
            previous,
            rfam_hits,
            r2dt_hits,
        });
    }
}

pub fn write_metadata(
    coordinate_file: &Path,
    rfam_hits_file: &Path,
    r2dt_hits_file: &Path,
    previous_file: &Path,
    xref_file: &Path,
    output: &Path,
) -> Result<()> {
    let xrefs = JsonlIterator::from_path(xref_file)?;
    let xrefs = xrefs.group_by(|x: &Xref| x.urs_taxid.to_owned());
    let xrefs = xrefs.into_iter().assume_sorted_by_key();

    let coordinates = JsonlIterator::from_path(coordinate_file)?;
    let coordinates = coordinates.group_by(|c: &Coordinate| c.urs_taxid.to_owned());
    let coordinates = coordinates.into_iter().assume_sorted_by_key();

    let rfam_hits = JsonlIterator::from_path(rfam_hits_file)?;
    let rfam_hits = rfam_hits.group_by(|h: &RfamHit| h.urs_taxid.to_owned());
    let rfam_hits = rfam_hits.into_iter().assume_sorted_by_key();

    let r2dt_hits = JsonlIterator::from_path(r2dt_hits_file)?;
    let r2dt_hits = r2dt_hits.group_by(|h: &R2dtHit| h.urs_taxid.to_owned());
    let r2dt_hits = r2dt_hits.into_iter().assume_sorted_by_key();

    let previous = JsonlIterator::from_path(previous_file)?;
    let previous = previous.group_by(|p: &Previous| p.urs_taxid.to_owned());
    let previous = previous.into_iter().assume_sorted_by_key();

    let partial =
        xrefs.left_join(coordinates).left_join(rfam_hits).left_join(r2dt_hits).left_join(previous);

    let mut output = rnc_utils::buf_writer(output)?;
    for (id, data) in partial {
        let ((((xrefs, coordinates), rfam_hits), r2dt_hits), previous) = data;
        let norm = Metadata::new(id, xrefs, coordinates, rfam_hits, r2dt_hits, previous)?;
        serde_json::to_writer(&mut output, &norm)?;
        writeln!(&mut output)?;
    }

    Ok(())
}

pub fn write(
    accession_file: &Path,
    coordinate_file: &Path,
    rfam_hits_file: &Path,
    r2dt_hits_file: &Path,
    previous_file: &Path,
    xref_file: &Path,
    output: &Path,
) -> Result<()> {
    let accessions = JsonlIterator::from_path(accession_file)?;
    let accessions = accessions.group_by(|a: &RawAccessionEntry| a.urs_taxid.to_owned());
    let accessions = accessions.into_iter().assume_sorted_by_key();

    let xrefs = JsonlIterator::from_path(xref_file)?;
    let xrefs = xrefs.group_by(|x: &Xref| x.urs_taxid.to_owned());
    let xrefs = xrefs.into_iter().assume_sorted_by_key();

    let coordinates = JsonlIterator::from_path(coordinate_file)?;
    let coordinates = coordinates.group_by(|c: &Coordinate| c.urs_taxid.to_owned());
    let coordinates = coordinates.into_iter().assume_sorted_by_key();

    let rfam_hits = JsonlIterator::from_path(rfam_hits_file)?;
    let rfam_hits = rfam_hits.group_by(|h: &RfamHit| h.urs_taxid.to_owned());
    let rfam_hits = rfam_hits.into_iter().assume_sorted_by_key();

    let r2dt_hits = JsonlIterator::from_path(r2dt_hits_file)?;
    let r2dt_hits = r2dt_hits.group_by(|h: &R2dtHit| h.urs_taxid.to_owned());
    let r2dt_hits = r2dt_hits.into_iter().assume_sorted_by_key();

    let previous = JsonlIterator::from_path(previous_file)?;
    let previous = previous.group_by(|p: &Previous| p.urs_taxid.to_owned());
    let previous = previous.into_iter().assume_sorted_by_key();

    let partial = accessions
        .join(xrefs)
        .left_join(coordinates)
        .left_join(rfam_hits)
        .left_join(r2dt_hits)
        .left_join(previous);

    let mut output = rnc_utils::buf_writer(output)?;
    for (id, data) in partial {
        let (((((accessions, xrefs), coordinates), rfam_hits), r2dt_hits), previous) = data;
        let norm =
            Normalized::new(id, accessions, xrefs, coordinates, rfam_hits, r2dt_hits, previous)?;
        serde_json::to_writer(&mut output, &norm)?;
        writeln!(&mut output)?;
    }

    Ok(())
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Commands that the GPU will execute (includes draw commands).
//!
//! With Vulkan, before the GPU can do anything you must create a `CommandBuffer`. A command buffer
//! is a list of commands that will executed by the GPU. Once a command buffer is created, you can
//! execute it. A command buffer must always be created even for the most simple tasks.
//!
//! # Primary and secondary command buffers.
//!
//! There are three types of command buffers:
//!
//! - **Primary command buffers**. They can contain any command. They are the only type of command
//!   buffer that can be submitted to a queue.
//! - **Secondary "graphics" command buffers**. They can only contain draw and clear commands.
//!   They can only be called from a primary command buffer when inside a render pass.
//! - **Secondary "compute" command buffers**. They can only contain non-render-pass-related
//!   commands (ie. everything but drawing, clearing, etc.) and cannot enter a render pass. They
//!   can only be called from a primary command buffer outside of a render pass.
//!
//! Using secondary command buffers leads to slightly lower performances on the GPU, but they have
//! two advantages on the CPU side:
//!
//! - Building a command buffer is a single-threaded operation, but by using secondary command
//!   buffers you can build multiple secondary command buffers in multiple threads simultaneously.
//! - Secondary command buffers can be kept alive between frames. When you always repeat the same
//!   operations, it might be a good idea to build a secondary command buffer once at
//!   initialization and then reuse it afterwards.
//!
//! # The `AutoCommandBufferBuilder`
//!
//! The most basic (and recommended) way to create a command buffer is to create a
//! [`AutoCommandBufferBuilder`](struct.AutoCommandBufferBuilder.html). Then use the
//! [`CommandBufferBuilder` trait](trait.CommandBufferBuilder.html) to add commands to it.
//! When you are done adding commands, use
//! [the `CommandBufferBuild` trait](trait.CommandBufferBuild.html) to obtain a
//! `AutoCommandBuffer`.
//!
//! Once built, use [the `CommandBuffer` trait](trait.CommandBuffer.html) to submit the command
//! buffer. Submitting a command buffer returns an object that implements the `GpuFuture` trait and
//! that represents the moment when the execution will end on the GPU.
//!
//! ```
//! use vulkano::command_buffer::AutoCommandBufferBuilder;
//! use vulkano::command_buffer::CommandBuffer;
//!
//! # let device: std::sync::Arc<vulkano::device::Device> = return;
//! # let queue: std::sync::Arc<vulkano::device::Queue> = return;
//! let cb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap()
//!     // TODO: add an actual command to this example
//!     .build().unwrap();
//!
//! let _future = cb.execute(queue.clone());
//! ```
//!
//! # Internal architecture of vulkano
//!
//! The `commands_raw` and `commands_extra` modules contain structs that correspond to various
//! commands that can be added to command buffer builders. A command can be added to a command
//! buffer builder by using the `AddCommand<C>` trait, where `C` is the command struct.
//!
//! The `AutoCommandBufferBuilder` internally uses a `UnsafeCommandBufferBuilder` wrapped around
//! multiple layers. See the `cb` module for more information.
//!
//! Command pools are automatically handled by default, but vulkano also allows you to use
//! alternative command pool implementations and use them. See the `pool` module for more
//! information.

pub use self::auto::AutoCommandBuffer;
pub use self::auto::AutoCommandBufferBuilder;
pub use self::state_cacher::StateCacher;
pub use self::state_cacher::StateCacherOutcome;
pub use self::traits::CommandBuffer;
pub use self::traits::CommandBufferBuild;
pub use self::traits::CommandBufferExecError;
pub use self::traits::CommandBufferExecFuture;

use pipeline::viewport::Scissor;
use pipeline::viewport::Viewport;

pub mod pool;
pub mod submit;
pub mod synced;
pub mod sys;
pub mod validity;

mod auto;
mod state_cacher;
mod traits;

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DrawIndirectCommand {
    pub vertex_count: u32,
    pub instance_count: u32,
    pub first_vertex: u32,
    pub first_instance: u32,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DrawIndexedIndirectCommand {
    pub index_count: u32,
    pub instance_count: u32,
    pub first_index: u32,
    pub vertex_offset: u32,
    pub first_instance: u32,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DispatchIndirectCommand {
    pub x: u32,
    pub y: u32,
    pub z: u32,
}

/// The dynamic state to use for a draw command.
// TODO: probably not the right location
#[derive(Debug, Clone)]
pub struct DynamicState {
    pub line_width: Option<f32>,
    pub viewports: Option<Vec<Viewport>>,
    pub scissors: Option<Vec<Scissor>>,
    // TODO: missing fields
}

impl DynamicState {
    #[inline]
    pub fn none() -> DynamicState {
        DynamicState {
            line_width: None,
            viewports: None,
            scissors: None,
        }
    }
}

impl Default for DynamicState {
    #[inline]
    fn default() -> DynamicState {
        DynamicState::none()
    }
}
<commit_msg>Re-export errors for AutoCommandBufferBuilder<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Commands that the GPU will execute (includes draw commands).
//!
//! With Vulkan, before the GPU can do anything you must create a `CommandBuffer`. A command buffer
//! is a list of commands that will executed by the GPU. Once a command buffer is created, you can
//! execute it. A command buffer must always be created even for the most simple tasks.
//!
//! # Primary and secondary command buffers.
//!
//! There are three types of command buffers:
//!
//! - **Primary command buffers**. They can contain any command. They are the only type of command
//!   buffer that can be submitted to a queue.
//! - **Secondary "graphics" command buffers**. They can only contain draw and clear commands.
//!   They can only be called from a primary command buffer when inside a render pass.
//! - **Secondary "compute" command buffers**. They can only contain non-render-pass-related
//!   commands (ie. everything but drawing, clearing, etc.) and cannot enter a render pass. They
//!   can only be called from a primary command buffer outside of a render pass.
//!
//! Using secondary command buffers leads to slightly lower performances on the GPU, but they have
//! two advantages on the CPU side:
//!
//! - Building a command buffer is a single-threaded operation, but by using secondary command
//!   buffers you can build multiple secondary command buffers in multiple threads simultaneously.
//! - Secondary command buffers can be kept alive between frames. When you always repeat the same
//!   operations, it might be a good idea to build a secondary command buffer once at
//!   initialization and then reuse it afterwards.
//!
//! # The `AutoCommandBufferBuilder`
//!
//! The most basic (and recommended) way to create a command buffer is to create a
//! [`AutoCommandBufferBuilder`](struct.AutoCommandBufferBuilder.html). Then use the
//! [`CommandBufferBuilder` trait](trait.CommandBufferBuilder.html) to add commands to it.
//! When you are done adding commands, use
//! [the `CommandBufferBuild` trait](trait.CommandBufferBuild.html) to obtain a
//! `AutoCommandBuffer`.
//!
//! Once built, use [the `CommandBuffer` trait](trait.CommandBuffer.html) to submit the command
//! buffer. Submitting a command buffer returns an object that implements the `GpuFuture` trait and
//! that represents the moment when the execution will end on the GPU.
//!
//! ```
//! use vulkano::command_buffer::AutoCommandBufferBuilder;
//! use vulkano::command_buffer::CommandBuffer;
//!
//! # let device: std::sync::Arc<vulkano::device::Device> = return;
//! # let queue: std::sync::Arc<vulkano::device::Queue> = return;
//! let cb = AutoCommandBufferBuilder::new(device.clone(), queue.family()).unwrap()
//!     // TODO: add an actual command to this example
//!     .build().unwrap();
//!
//! let _future = cb.execute(queue.clone());
//! ```
//!
//! # Internal architecture of vulkano
//!
//! The `commands_raw` and `commands_extra` modules contain structs that correspond to various
//! commands that can be added to command buffer builders. A command can be added to a command
//! buffer builder by using the `AddCommand<C>` trait, where `C` is the command struct.
//!
//! The `AutoCommandBufferBuilder` internally uses a `UnsafeCommandBufferBuilder` wrapped around
//! multiple layers. See the `cb` module for more information.
//!
//! Command pools are automatically handled by default, but vulkano also allows you to use
//! alternative command pool implementations and use them. See the `pool` module for more
//! information.

pub use self::auto::AutoCommandBuffer;
pub use self::auto::AutoCommandBufferBuilder;
pub use self::auto::AutoCommandBufferBuilderContextError;
pub use self::auto::BeginRenderPassError;
pub use self::auto::BlitImageError;
pub use self::auto::BuildError;
pub use self::auto::ClearColorImageError;
pub use self::auto::CopyBufferError;
pub use self::auto::CopyBufferImageError;
pub use self::auto::DispatchError;
pub use self::auto::DrawError;
pub use self::auto::DrawIndexedError;
pub use self::auto::DrawIndirectError;
pub use self::auto::ExecuteCommandsError;
pub use self::auto::FillBufferError;
pub use self::auto::UpdateBufferError;
pub use self::state_cacher::StateCacher;
pub use self::state_cacher::StateCacherOutcome;
pub use self::traits::CommandBuffer;
pub use self::traits::CommandBufferBuild;
pub use self::traits::CommandBufferExecError;
pub use self::traits::CommandBufferExecFuture;

use pipeline::viewport::Scissor;
use pipeline::viewport::Viewport;

pub mod pool;
pub mod submit;
pub mod synced;
pub mod sys;
pub mod validity;

mod auto;
mod state_cacher;
mod traits;

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DrawIndirectCommand {
    pub vertex_count: u32,
    pub instance_count: u32,
    pub first_vertex: u32,
    pub first_instance: u32,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DrawIndexedIndirectCommand {
    pub index_count: u32,
    pub instance_count: u32,
    pub first_index: u32,
    pub vertex_offset: u32,
    pub first_instance: u32,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub struct DispatchIndirectCommand {
    pub x: u32,
    pub y: u32,
    pub z: u32,
}

/// The dynamic state to use for a draw command.
// TODO: probably not the right location
#[derive(Debug, Clone)]
pub struct DynamicState {
    pub line_width: Option<f32>,
    pub viewports: Option<Vec<Viewport>>,
    pub scissors: Option<Vec<Scissor>>,
    // TODO: missing fields
}

impl DynamicState {
    #[inline]
    pub fn none() -> DynamicState {
        DynamicState {
            line_width: None,
            viewports: None,
            scissors: None,
        }
    }
}

impl Default for DynamicState {
    #[inline]
    fn default() -> DynamicState {
        DynamicState::none()
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! single_pass_renderpass {
    (
        attachments: { $($a:tt)* },
        pass: {
            color: [$($color_atch:ident),*],
            depth_stencil: {$($depth_atch:ident)*}
        }
    ) => {
        ordered_passes_renderpass!{
            attachments: { $($a)* },
            passes: [
                {
                    color: [$($color_atch),*],
                    depth_stencil: {$($depth_atch)*},
                    input: []
                }
            ]
        }
    }
}

/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! ordered_passes_renderpass {
    (
        attachments: {
            $(
                $atch_name:ident: {
                    load: $load:ident,
                    store: $store:ident,
                    format: $format:ty,
                }
            ),*
        },
        passes: [
            $(
                {
                    color: [$($color_atch:ident),*],
                    depth_stencil: {$($depth_atch:ident)*},
                    input: [$($input_atch:ident),*]
                }
            ),*
        ]
    ) => {
        use std::vec::IntoIter as VecIntoIter;
        use std::sync::Arc;
        use $crate::OomError;
        use $crate::device::Device;
        use $crate::format::ClearValue;
        use $crate::framebuffer::UnsafeRenderPass;
        use $crate::framebuffer::RenderPass;
        use $crate::framebuffer::RenderPassDesc;
        use $crate::framebuffer::RenderPassClearValues;
        use $crate::framebuffer::RenderPassAttachmentsList;
        use $crate::framebuffer::LayoutAttachmentDescription;
        use $crate::framebuffer::LayoutPassDescription;
        use $crate::framebuffer::LayoutPassDependencyDescription;
        use $crate::framebuffer::FramebufferCreationError;
        use $crate::image::Layout;
        use $crate::image::traits::Image;
        use $crate::image::traits::ImageView;

        #[derive(Debug, Clone)]
        pub struct Formats {
            $(
                pub $atch_name: ($format, u32),
            )*
        }

        pub struct CustomRenderPass {
            render_pass: UnsafeRenderPass,
            formats: Formats,
        }

        impl CustomRenderPass {
            pub fn raw(device: &Arc<Device>, formats: &Formats)
                       -> Result<CustomRenderPass, OomError>
            {
                #![allow(unsafe_code)]

                let rp = try!(unsafe {
                    UnsafeRenderPass::raw(device, AttachmentsIter(formats.clone(), 0),
                                          PassesIter(0), DependenciesIter(0, 0))
                });

                Ok(CustomRenderPass {
                    render_pass: rp,
                    formats: formats.clone(),
                })
            }

            #[inline]
            pub fn new(device: &Arc<Device>, formats: &Formats)
                       -> Arc<CustomRenderPass>
            {
                Arc::new(CustomRenderPass::raw(device, formats).unwrap())
            }
        }

        unsafe impl RenderPass for CustomRenderPass {
            #[inline]
            fn render_pass(&self) -> &UnsafeRenderPass {
                &self.render_pass
            }
        }

        unsafe impl RenderPassDesc for CustomRenderPass {
            type AttachmentsIter = AttachmentsIter;
            type PassesIter = PassesIter;
            type DependenciesIter = DependenciesIter;

            #[inline]
            fn attachments(&self) -> Self::AttachmentsIter {
                AttachmentsIter(self.formats.clone(), 0)
            }

            #[inline]
            fn passes(&self) -> Self::PassesIter {
                PassesIter(0)
            }

            #[inline]
            fn dependencies(&self) -> Self::DependenciesIter {
                DependenciesIter(0, 0)
            }
        }

        #[derive(Debug, Clone)]
        pub struct AttachmentsIter(Formats, usize);
        impl ExactSizeIterator for AttachmentsIter {}
        impl Iterator for AttachmentsIter {
            type Item = LayoutAttachmentDescription;

            #[inline]
            fn next(&mut self) -> Option<LayoutAttachmentDescription> {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]

                let mut num = 0;

                $({
                    if self.1 == num {
                        self.1 += 1;

                        let (initial_layout, final_layout) = attachment_layouts(num);

                        return Some($crate::framebuffer::LayoutAttachmentDescription {
                            format: $crate::format::FormatDesc::format(&(self.0).$atch_name.0),
                            samples: (self.0).$atch_name.1,
                            load: $crate::framebuffer::LoadOp::$load,
                            store: $crate::framebuffer::StoreOp::$store,
                            initial_layout: initial_layout,
                            final_layout: final_layout,
                        });
                    }

                    num += 1;
                })*

                None
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                let mut num = 0;
                $(let $atch_name = num; num += 1;)*
                num -= self.1;
                (num, Some(num))
            }
        }

        #[derive(Debug, Clone)]
        pub struct PassesIter(usize);
        impl ExactSizeIterator for PassesIter {}
        impl Iterator for PassesIter {
            type Item = LayoutPassDescription;

            #[inline]
            fn next(&mut self) -> Option<LayoutPassDescription> {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]

                let mut attachment_num = 0;
                $(
                    let $atch_name = attachment_num;
                    attachment_num += 1;
                )*

                let mut cur_pass_num = 0;

                $({
                    if self.0 == cur_pass_num {
                        self.0 += 1;

                        let mut depth = None;
                        $(
                            depth = Some(($depth_atch, Layout::DepthStencilAttachmentOptimal));
                        )*

                        return Some(LayoutPassDescription {
                            color_attachments: vec![
                                $(
                                    ($color_atch, Layout::ColorAttachmentOptimal)
                                ),*
                            ],
                            depth_stencil: depth,
                            input_attachments: vec![
                                $(
                                    ($input_atch, Layout::ShaderReadOnlyOptimal)
                                ),*
                            ],
                            resolve_attachments: vec![],
                            preserve_attachments: (0 .. attachment_num).filter(|&a| {
                                $(if a == $color_atch { return false; })*
                                $(if a == $depth_atch { return false; })*
                                $(if a == $input_atch { return false; })*
                                true
                            }).collect()
                        });
                    }

                    cur_pass_num += 1;
                }),*

                None
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                let mut num = 0;
                $($(let $color_atch = num;)* num += 1;)*
                num -= self.0;
                (num, Some(num))
            }
        }

        #[derive(Debug, Clone)]
        pub struct DependenciesIter(usize, usize);
        impl ExactSizeIterator for DependenciesIter {}
        impl Iterator for DependenciesIter {
            type Item = LayoutPassDependencyDescription;

            #[inline]
            fn next(&mut self) -> Option<LayoutPassDependencyDescription> {
                let num_passes = PassesIter(0).len();

                self.1 += 1;
                if self.1 >= num_passes {
                    self.0 += 1;
                    self.1 = self.0 + 1;
                }

                if self.0 >= num_passes || self.1 >= num_passes {
                    return None;
                }

                Some(LayoutPassDependencyDescription {
                    source_subpass: self.0,
                    destination_subpass: self.1,
                    by_region: false,
                })
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                let num_passes = PassesIter(0).len();

                let out = (num_passes - self.1 - 1) +
                          ((self.0 + 1) .. num_passes).map(|p| p * (num_passes - p - 1))
                                                      .fold(0, |a, b| a + b);
                (out, Some(out))
            }
        }

        /// Returns the initial and final layout of an attachment, given its num.
        ///
        /// The value always correspond to the first and last usages of an attachment.
        fn attachment_layouts(num: usize) -> (Layout, Layout) {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            let mut attachment_num = 0;
            $(
                let $atch_name = attachment_num;
                attachment_num += 1;
            )*

            let mut initial_layout = None;
            let mut final_layout = None;

            $({
                $(
                    if $depth_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::DepthStencilAttachmentOptimal);
                        }
                        final_layout = Some(Layout::DepthStencilAttachmentOptimal);
                    }
                )*

                $(
                    if $color_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::ColorAttachmentOptimal);
                        }
                        final_layout = Some(Layout::ColorAttachmentOptimal);
                    }
                )*

                $(
                    if $input_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::ShaderReadOnlyOptimal);
                        }
                        final_layout = Some(Layout::ShaderReadOnlyOptimal);
                    }
                )*
            })*

            (initial_layout.unwrap(), final_layout.unwrap())
        }

        #[allow(non_camel_case_types)]
        pub struct AList<'a, $($atch_name: 'a),*> {
            $(
                pub $atch_name: &'a Arc<$atch_name>,
            )*
        }

        #[allow(non_camel_case_types)]
        unsafe impl<'a, $($atch_name: 'static + ImageView),*> RenderPassAttachmentsList<AList<'a, $($atch_name),*>> for CustomRenderPass {
            // TODO: shouldn't build a Vec
            type AttachmentsIter = VecIntoIter<(Arc<ImageView>, Arc<Image>, Layout, Layout)>;

            #[inline]
            fn convert_attachments_list(&self, l: AList<'a, $($atch_name),*>) -> Result<Self::AttachmentsIter, FramebufferCreationError> {
                #![allow(unused_assignments)]

                let mut result = Vec::new();

                let mut num = 0;
                $({
                    if !l.$atch_name.identity_swizzle() {
                        return Err(FramebufferCreationError::AttachmentNotIdentitySwizzled);
                    }

                    // FIXME: lots of checks missing (format, samples, layout, etc.)

                    let (initial_layout, final_layout) = attachment_layouts(num);
                    num += 1;
                    result.push((l.$atch_name.clone() as Arc<_>, ImageView::parent_arc(&l.$atch_name), initial_layout, final_layout));
                })*

                Ok(result.into_iter())
            }
        }

        ordered_passes_renderpass!{__impl_clear_values__ [0] [] [$($atch_name $format, $load,)*] }

        unsafe impl RenderPassClearValues<ClearValues> for CustomRenderPass {
            type ClearValuesIter = ClearValuesIter;

            #[inline]
            fn convert_clear_values(&self, val: ClearValues) -> ClearValuesIter {
                ClearValuesIter(val, 0)
            }
        }
    };

    (__impl_clear_values__ [$num:expr] [$($s:tt)*] [$atch_name:ident $format:ty, Clear, $($rest:tt)*]) => {
        ordered_passes_renderpass!{__impl_clear_values__ [$num+1] [$($s)* $atch_name [$num] $format,] [$($rest)*] }
    };

    (__impl_clear_values__ [$num:expr] [$($s:tt)*] [$atch_name:ident $format:ty, $misc:ident, $($rest:tt)*]) => {
        ordered_passes_renderpass!{__impl_clear_values__ [$num+1] [$($s)*] [$($rest)*] }
    };

    (__impl_clear_values__ [$total:expr] [$($atch:ident [$num:expr] $format:ty,)+] []) => {
        pub struct ClearValues {
            $(
                pub $atch: <$format as $crate::format::FormatDesc>::ClearValue,
            )+
        }

        pub struct ClearValuesIter(ClearValues, usize);

        impl Iterator for ClearValuesIter {
            type Item = $crate::format::ClearValue;

            #[inline]
            fn next(&mut self) -> Option<Self::Item> {
                $(
                    if self.1 == $num {
                        self.1 += 1;
                        return Some(ClearValue::from((self.0).$atch));        // FIXME: should use Format::decode_clear_value instead
                    }
                )+

                if self.1 >= $total {
                    None
                } else {
                    Some(ClearValue::None)
                }
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                let len = $total - self.1;
                (len, Some(len))
            }
        }

        impl ExactSizeIterator for ClearValuesIter {}
    };

    (__impl_clear_values__ [$total:expr] [] []) => {
        pub type ClearValues = ();

        pub struct ClearValuesIter((), usize);

        impl Iterator for ClearValuesIter {
            type Item = $crate::format::ClearValue;
            #[inline]
            fn next(&mut self) -> Option<Self::Item> { None }
            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) { (0, Some(0)) }
        }

        impl ExactSizeIterator for ClearValuesIter {}
    };
}
<commit_msg>Allow specifying the initial and final layouts in the render pass macro<commit_after>// Copyright (c) 2016 The vulkano developers
// 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. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! single_pass_renderpass {
    (
        attachments: { $($a:tt)* },
        pass: {
            color: [$($color_atch:ident),*],
            depth_stencil: {$($depth_atch:ident)*}
        }
    ) => {
        ordered_passes_renderpass!{
            attachments: { $($a)* },
            passes: [
                {
                    color: [$($color_atch),*],
                    depth_stencil: {$($depth_atch)*},
                    input: []
                }
            ]
        }
    }
}

/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! ordered_passes_renderpass {
    (
        attachments: {
            $(
                $atch_name:ident: {
                    load: $load:ident,
                    store: $store:ident,
                    format: $format:ty,
                    $(initial_layout: $init_layout:expr,)*
                    $(final_layout: $final_layout:expr,)*
                }
            ),*
        },
        passes: [
            $(
                {
                    color: [$($color_atch:ident),*],
                    depth_stencil: {$($depth_atch:ident)*},
                    input: [$($input_atch:ident),*]
                }
            ),*
        ]
    ) => {
        use std::vec::IntoIter as VecIntoIter;
        use std::sync::Arc;
        use $crate::OomError;
        use $crate::device::Device;
        use $crate::format::ClearValue;
        use $crate::framebuffer::UnsafeRenderPass;
        use $crate::framebuffer::RenderPass;
        use $crate::framebuffer::RenderPassDesc;
        use $crate::framebuffer::RenderPassClearValues;
        use $crate::framebuffer::RenderPassAttachmentsList;
        use $crate::framebuffer::LayoutAttachmentDescription;
        use $crate::framebuffer::LayoutPassDescription;
        use $crate::framebuffer::LayoutPassDependencyDescription;
        use $crate::framebuffer::FramebufferCreationError;
        use $crate::image::Layout;
        use $crate::image::traits::Image;
        use $crate::image::traits::ImageView;

        #[derive(Debug, Clone)]
        pub struct Formats {
            $(
                pub $atch_name: ($format, u32),
            )*
        }

        pub struct CustomRenderPass {
            render_pass: UnsafeRenderPass,
            formats: Formats,
        }

        impl CustomRenderPass {
            pub fn raw(device: &Arc<Device>, formats: &Formats)
                       -> Result<CustomRenderPass, OomError>
            {
                #![allow(unsafe_code)]

                let rp = try!(unsafe {
                    UnsafeRenderPass::raw(device, AttachmentsIter(formats.clone(), 0),
                                          PassesIter(0), DependenciesIter(0, 0))
                });

                Ok(CustomRenderPass {
                    render_pass: rp,
                    formats: formats.clone(),
                })
            }

            #[inline]
            pub fn new(device: &Arc<Device>, formats: &Formats)
                       -> Arc<CustomRenderPass>
            {
                Arc::new(CustomRenderPass::raw(device, formats).unwrap())
            }
        }

        unsafe impl RenderPass for CustomRenderPass {
            #[inline]
            fn render_pass(&self) -> &UnsafeRenderPass {
                &self.render_pass
            }
        }

        unsafe impl RenderPassDesc for CustomRenderPass {
            type AttachmentsIter = AttachmentsIter;
            type PassesIter = PassesIter;
            type DependenciesIter = DependenciesIter;

            #[inline]
            fn attachments(&self) -> Self::AttachmentsIter {
                AttachmentsIter(self.formats.clone(), 0)
            }

            #[inline]
            fn passes(&self) -> Self::PassesIter {
                PassesIter(0)
            }

            #[inline]
            fn dependencies(&self) -> Self::DependenciesIter {
                DependenciesIter(0, 0)
            }
        }

        #[derive(Debug, Clone)]
        pub struct AttachmentsIter(Formats, usize);
        impl ExactSizeIterator for AttachmentsIter {}
        impl Iterator for AttachmentsIter {
            type Item = LayoutAttachmentDescription;

            #[inline]
            fn next(&mut self) -> Option<LayoutAttachmentDescription> {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]

                let mut num = 0;

                $({
                    if self.1 == num {
                        self.1 += 1;

                        let (initial_layout, final_layout) = attachment_layouts(num);

                        return Some($crate::framebuffer::LayoutAttachmentDescription {
                            format: $crate::format::FormatDesc::format(&(self.0).$atch_name.0),
                            samples: (self.0).$atch_name.1,
                            load: $crate::framebuffer::LoadOp::$load,
                            store: $crate::framebuffer::StoreOp::$store,
                            initial_layout: initial_layout,
                            final_layout: final_layout,
                        });
                    }

                    num += 1;
                })*

                None
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                let mut num = 0;
                $(let $atch_name = num; num += 1;)*
                num -= self.1;
                (num, Some(num))
            }
        }

        #[derive(Debug, Clone)]
        pub struct PassesIter(usize);
        impl ExactSizeIterator for PassesIter {}
        impl Iterator for PassesIter {
            type Item = LayoutPassDescription;

            #[inline]
            fn next(&mut self) -> Option<LayoutPassDescription> {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]

                let mut attachment_num = 0;
                $(
                    let $atch_name = attachment_num;
                    attachment_num += 1;
                )*

                let mut cur_pass_num = 0;

                $({
                    if self.0 == cur_pass_num {
                        self.0 += 1;

                        let mut depth = None;
                        $(
                            depth = Some(($depth_atch, Layout::DepthStencilAttachmentOptimal));
                        )*

                        return Some(LayoutPassDescription {
                            color_attachments: vec![
                                $(
                                    ($color_atch, Layout::ColorAttachmentOptimal)
                                ),*
                            ],
                            depth_stencil: depth,
                            input_attachments: vec![
                                $(
                                    ($input_atch, Layout::ShaderReadOnlyOptimal)
                                ),*
                            ],
                            resolve_attachments: vec![],
                            preserve_attachments: (0 .. attachment_num).filter(|&a| {
                                $(if a == $color_atch { return false; })*
                                $(if a == $depth_atch { return false; })*
                                $(if a == $input_atch { return false; })*
                                true
                            }).collect()
                        });
                    }

                    cur_pass_num += 1;
                }),*

                None
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                #![allow(unused_assignments)]
                #![allow(unused_mut)]
                let mut num = 0;
                $($(let $color_atch = num;)* num += 1;)*
                num -= self.0;
                (num, Some(num))
            }
        }

        #[derive(Debug, Clone)]
        pub struct DependenciesIter(usize, usize);
        impl ExactSizeIterator for DependenciesIter {}
        impl Iterator for DependenciesIter {
            type Item = LayoutPassDependencyDescription;

            #[inline]
            fn next(&mut self) -> Option<LayoutPassDependencyDescription> {
                let num_passes = PassesIter(0).len();

                self.1 += 1;
                if self.1 >= num_passes {
                    self.0 += 1;
                    self.1 = self.0 + 1;
                }

                if self.0 >= num_passes || self.1 >= num_passes {
                    return None;
                }

                Some(LayoutPassDependencyDescription {
                    source_subpass: self.0,
                    destination_subpass: self.1,
                    by_region: false,
                })
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                let num_passes = PassesIter(0).len();

                let out = (num_passes - self.1 - 1) +
                          ((self.0 + 1) .. num_passes).map(|p| p * (num_passes - p - 1))
                                                      .fold(0, |a, b| a + b);
                (out, Some(out))
            }
        }

        /// Returns the initial and final layout of an attachment, given its num.
        ///
        /// The value always correspond to the first and last usages of an attachment.
        fn attachment_layouts(num: usize) -> (Layout, Layout) {
            #![allow(unused_assignments)]
            #![allow(unused_mut)]

            let mut attachment_num = 0;
            $(
                let $atch_name = attachment_num;
                attachment_num += 1;
            )*

            let mut initial_layout = None;
            let mut final_layout = None;

            $({
                $(
                    if $depth_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::DepthStencilAttachmentOptimal);
                        }
                        final_layout = Some(Layout::DepthStencilAttachmentOptimal);
                    }
                )*

                $(
                    if $color_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::ColorAttachmentOptimal);
                        }
                        final_layout = Some(Layout::ColorAttachmentOptimal);
                    }
                )*

                $(
                    if $input_atch == num {
                        if initial_layout.is_none() {
                            initial_layout = Some(Layout::ShaderReadOnlyOptimal);
                        }
                        final_layout = Some(Layout::ShaderReadOnlyOptimal);
                    }
                )*
            })*

            $(if $atch_name == num {
                $(initial_layout = Some($init_layout);)*
                $(final_layout = Some($final_layout);)*
            })*

            (initial_layout.unwrap(), final_layout.unwrap())
        }

        #[allow(non_camel_case_types)]
        pub struct AList<'a, $($atch_name: 'a),*> {
            $(
                pub $atch_name: &'a Arc<$atch_name>,
            )*
        }

        #[allow(non_camel_case_types)]
        unsafe impl<'a, $($atch_name: 'static + ImageView),*> RenderPassAttachmentsList<AList<'a, $($atch_name),*>> for CustomRenderPass {
            // TODO: shouldn't build a Vec
            type AttachmentsIter = VecIntoIter<(Arc<ImageView>, Arc<Image>, Layout, Layout)>;

            #[inline]
            fn convert_attachments_list(&self, l: AList<'a, $($atch_name),*>) -> Result<Self::AttachmentsIter, FramebufferCreationError> {
                #![allow(unused_assignments)]

                let mut result = Vec::new();

                let mut num = 0;
                $({
                    if !l.$atch_name.identity_swizzle() {
                        return Err(FramebufferCreationError::AttachmentNotIdentitySwizzled);
                    }

                    // FIXME: lots of checks missing (format, samples, layout, etc.)

                    let (initial_layout, final_layout) = attachment_layouts(num);
                    num += 1;
                    result.push((l.$atch_name.clone() as Arc<_>, ImageView::parent_arc(&l.$atch_name), initial_layout, final_layout));
                })*

                Ok(result.into_iter())
            }
        }

        ordered_passes_renderpass!{__impl_clear_values__ [0] [] [$($atch_name $format, $load,)*] }

        unsafe impl RenderPassClearValues<ClearValues> for CustomRenderPass {
            type ClearValuesIter = ClearValuesIter;

            #[inline]
            fn convert_clear_values(&self, val: ClearValues) -> ClearValuesIter {
                ClearValuesIter(val, 0)
            }
        }
    };

    (__impl_clear_values__ [$num:expr] [$($s:tt)*] [$atch_name:ident $format:ty, Clear, $($rest:tt)*]) => {
        ordered_passes_renderpass!{__impl_clear_values__ [$num+1] [$($s)* $atch_name [$num] $format,] [$($rest)*] }
    };

    (__impl_clear_values__ [$num:expr] [$($s:tt)*] [$atch_name:ident $format:ty, $misc:ident, $($rest:tt)*]) => {
        ordered_passes_renderpass!{__impl_clear_values__ [$num+1] [$($s)*] [$($rest)*] }
    };

    (__impl_clear_values__ [$total:expr] [$($atch:ident [$num:expr] $format:ty,)+] []) => {
        pub struct ClearValues {
            $(
                pub $atch: <$format as $crate::format::FormatDesc>::ClearValue,
            )+
        }

        pub struct ClearValuesIter(ClearValues, usize);

        impl Iterator for ClearValuesIter {
            type Item = $crate::format::ClearValue;

            #[inline]
            fn next(&mut self) -> Option<Self::Item> {
                $(
                    if self.1 == $num {
                        self.1 += 1;
                        return Some(ClearValue::from((self.0).$atch));        // FIXME: should use Format::decode_clear_value instead
                    }
                )+

                if self.1 >= $total {
                    None
                } else {
                    Some(ClearValue::None)
                }
            }

            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) {
                let len = $total - self.1;
                (len, Some(len))
            }
        }

        impl ExactSizeIterator for ClearValuesIter {}
    };

    (__impl_clear_values__ [$total:expr] [] []) => {
        pub type ClearValues = ();

        pub struct ClearValuesIter((), usize);

        impl Iterator for ClearValuesIter {
            type Item = $crate::format::ClearValue;
            #[inline]
            fn next(&mut self) -> Option<Self::Item> { None }
            #[inline]
            fn size_hint(&self) -> (usize, Option<usize>) { (0, Some(0)) }
        }

        impl ExactSizeIterator for ClearValuesIter {}
    };
}
<|endoftext|>