<commit_before>#![warn(clippy::all, rust_2018_idioms)]

#[macro_use]
extern crate claim;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_json;

use crate::util::{RequestHelper, TestApp};
use cargo_registry::{
    models::{Crate, CrateOwner, Dependency, NewCategory, NewTeam, NewUser, Team, User, Version},
    schema::crate_owners,
    util::AppResponse,
    views::{
        EncodableCategory, EncodableCategoryWithSubcategories, EncodableCrate, EncodableKeyword,
        EncodableOwner, EncodableVersion, GoodCrate,
    },
    App, Config, Env, Replica, Uploader,
};
use std::{
    borrow::Cow,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
};

use conduit::{header, Body};
use conduit_test::MockRequest;
use diesel::prelude::*;
use reqwest::{blocking::Client, Proxy};

mod account_lock;
mod authentication;
mod badge;
mod builders;
mod categories;
mod category;
mod dump_db;
mod git;
mod keyword;
mod krate;
mod owners;
mod read_only_mode;
mod record;
mod schema_details;
mod server;
mod team;
mod token;
mod user;
mod util;
mod version;

#[derive(Deserialize)]
pub struct CrateList {
    crates: Vec<EncodableCrate>,
    meta: CrateMeta,
}
#[derive(Deserialize)]
struct CrateMeta {
    total: i32,
    next_page: Option<String>,
    prev_page: Option<String>,
}
#[derive(Deserialize)]
pub struct CrateResponse {
    #[serde(rename = "crate")]
    krate: EncodableCrate,
    versions: Vec<EncodableVersion>,
    keywords: Vec<EncodableKeyword>,
}
#[derive(Deserialize)]
pub struct VersionResponse {
    version: EncodableVersion,
}
#[derive(Deserialize)]
pub struct OwnerTeamsResponse {
    teams: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct OwnersResponse {
    users: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct CategoryResponse {
    category: EncodableCategoryWithSubcategories,
}
#[derive(Deserialize)]
pub struct CategoryListResponse {
    categories: Vec<EncodableCategory>,
    meta: CategoryMeta,
}
#[derive(Deserialize)]
pub struct CategoryMeta {
    total: i32,
}
#[derive(Deserialize)]
pub struct OkBool {
    ok: bool,
}

fn app() -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    build_app(simple_config(), None)
}

fn simple_config() -> Config {
    let uploader = Uploader::S3 {
        bucket: s3::Bucket::new(
            String::from("alexcrichton-test"),
            None,
            dotenv::var("S3_ACCESS_KEY").unwrap_or_default(),
            dotenv::var("S3_SECRET_KEY").unwrap_or_default(),
            // When testing we route all API traffic over HTTP so we can
            // sniff/record it, but everywhere else we use https
            "http",
        ),
        cdn: None,
    };

    Config {
        uploader,
        session_key: "test this has to be over 32 bytes long".to_string(),
        gh_client_id: dotenv::var("GH_CLIENT_ID").unwrap_or_default(),
        gh_client_secret: dotenv::var("GH_CLIENT_SECRET").unwrap_or_default(),
        db_url: env("TEST_DATABASE_URL"),
        replica_db_url: None,
        env: Env::Test,
        max_upload_size: 3000,
        max_unpack_size: 2000,
        mirror: Replica::Primary,
        // When testing we route all API traffic over HTTP so we can
        // sniff/record it, but everywhere else we use https
        api_protocol: String::from("http"),
        publish_rate_limit: Default::default(),
        blocked_traffic: Default::default(),
        domain_name: "crates.io".into(),
        allowed_origins: Vec::new(),
    }
}

fn build_app(
    config: Config,
    proxy: Option<String>,
) -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    let client = if let Some(proxy) = proxy {
        let mut builder = Client::builder();
        builder = builder
            .proxy(Proxy::all(&proxy).expect("Unable to configure proxy with the provided URL"));
        Some(builder.build().expect("TLS backend cannot be initialized"))
    } else {
        None
    };

    let app = App::new(config, client);
    assert_ok!(assert_ok!(app.primary_database.get()).begin_test_transaction());
    let app = Arc::new(app);
    let handler = cargo_registry::build_handler(Arc::clone(&app));
    (app, handler)
}

// Return the environment variable only if it has been defined
#[track_caller]
fn env(var: &str) -> String {
    match dotenv::var(var) {
        Ok(ref s) if s.is_empty() => panic!("environment variable `{}` must not be empty", var),
        Ok(s) => s,
        _ => panic!(
            "environment variable `{}` must be defined and valid unicode",
            var
        ),
    }
}

fn req(method: conduit::Method, path: &str) -> MockRequest {
    let mut request = MockRequest::new(method, path);
    request.header(header::USER_AGENT, "conduit-test");
    request
}

fn json<T>(r: &mut AppResponse) -> T
where
    for<'de> T: serde::Deserialize<'de>,
{
    use conduit::Body::*;

    let mut body = Body::empty();
    std::mem::swap(r.body_mut(), &mut body);
    let body: std::borrow::Cow<'static, [u8]> = match body {
        Static(slice) => slice.into(),
        Owned(vec) => vec.into(),
        File(_) => unimplemented!(),
    };

    let s = std::str::from_utf8(&body).unwrap();
    match serde_json::from_str(s) {
        Ok(t) => t,
        Err(e) => panic!("failed to decode: {:?}\n{}", e, s),
    }
}

static NEXT_GH_ID: AtomicUsize = AtomicUsize::new(0);

fn new_user(login: &str) -> NewUser<'_> {
    NewUser {
        gh_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        gh_login: login,
        name: None,
        gh_avatar: None,
        gh_access_token: Cow::Borrowed("some random token"),
    }
}

fn new_team(login: &str) -> NewTeam<'_> {
    NewTeam {
        org_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        github_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        login,
        name: None,
        avatar: None,
    }
}

fn add_team_to_crate(t: &Team, krate: &Crate, u: &User, conn: &PgConnection) -> QueryResult<()> {
    let crate_owner = CrateOwner {
        crate_id: krate.id,
        owner_id: t.id,
        created_by: u.id,
        owner_kind: 1, // Team owner kind is 1 according to owner.rs
        email_notifications: true,
    };

    diesel::insert_into(crate_owners::table)
        .values(&crate_owner)
        .on_conflict(crate_owners::table.primary_key())
        .do_update()
        .set(crate_owners::deleted.eq(false))
        .execute(conn)?;

    Ok(())
}

fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Dependency {
    use cargo_registry::schema::dependencies::dsl::*;
    use diesel::insert_into;

    insert_into(dependencies)
        .values((
            version_id.eq(version.id),
            crate_id.eq(krate.id),
            req.eq(">= 0"),
            optional.eq(false),
            default_features.eq(false),
            features.eq(Vec::<String>::new()),
        ))
        .get_result(conn)
        .unwrap()
}

fn new_category<'a>(category: &'a str, slug: &'a str, description: &'a str) -> NewCategory<'a> {
    NewCategory {
        category,
        slug,
        description,
    }
}

#[test]
fn multiple_live_references_to_the_same_connection_can_be_checked_out() {
    use std::ptr;

    let (app, _) = app();
    let conn1 = app.primary_database.get().unwrap();
    let conn2 = app.primary_database.get().unwrap();
    let conn1_ref: &PgConnection = &conn1;
    let conn2_ref: &PgConnection = &conn2;

    assert!(ptr::eq(conn1_ref, conn2_ref));
}
<commit_msg>tests: Import `log` macros<commit_after>#![warn(clippy::all, rust_2018_idioms)]

#[macro_use]
extern crate claim;
#[macro_use]
extern crate diesel;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde;
#[macro_use]
extern crate serde_json;

use crate::util::{RequestHelper, TestApp};
use cargo_registry::{
    models::{Crate, CrateOwner, Dependency, NewCategory, NewTeam, NewUser, Team, User, Version},
    schema::crate_owners,
    util::AppResponse,
    views::{
        EncodableCategory, EncodableCategoryWithSubcategories, EncodableCrate, EncodableKeyword,
        EncodableOwner, EncodableVersion, GoodCrate,
    },
    App, Config, Env, Replica, Uploader,
};
use std::{
    borrow::Cow,
    sync::{
        atomic::{AtomicUsize, Ordering},
        Arc,
    },
};

use conduit::{header, Body};
use conduit_test::MockRequest;
use diesel::prelude::*;
use reqwest::{blocking::Client, Proxy};

mod account_lock;
mod authentication;
mod badge;
mod builders;
mod categories;
mod category;
mod dump_db;
mod git;
mod keyword;
mod krate;
mod owners;
mod read_only_mode;
mod record;
mod schema_details;
mod server;
mod team;
mod token;
mod user;
mod util;
mod version;

#[derive(Deserialize)]
pub struct CrateList {
    crates: Vec<EncodableCrate>,
    meta: CrateMeta,
}
#[derive(Deserialize)]
struct CrateMeta {
    total: i32,
    next_page: Option<String>,
    prev_page: Option<String>,
}
#[derive(Deserialize)]
pub struct CrateResponse {
    #[serde(rename = "crate")]
    krate: EncodableCrate,
    versions: Vec<EncodableVersion>,
    keywords: Vec<EncodableKeyword>,
}
#[derive(Deserialize)]
pub struct VersionResponse {
    version: EncodableVersion,
}
#[derive(Deserialize)]
pub struct OwnerTeamsResponse {
    teams: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct OwnersResponse {
    users: Vec<EncodableOwner>,
}
#[derive(Deserialize)]
pub struct CategoryResponse {
    category: EncodableCategoryWithSubcategories,
}
#[derive(Deserialize)]
pub struct CategoryListResponse {
    categories: Vec<EncodableCategory>,
    meta: CategoryMeta,
}
#[derive(Deserialize)]
pub struct CategoryMeta {
    total: i32,
}
#[derive(Deserialize)]
pub struct OkBool {
    ok: bool,
}

fn app() -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    build_app(simple_config(), None)
}

fn simple_config() -> Config {
    let uploader = Uploader::S3 {
        bucket: s3::Bucket::new(
            String::from("alexcrichton-test"),
            None,
            dotenv::var("S3_ACCESS_KEY").unwrap_or_default(),
            dotenv::var("S3_SECRET_KEY").unwrap_or_default(),
            // When testing we route all API traffic over HTTP so we can
            // sniff/record it, but everywhere else we use https
            "http",
        ),
        cdn: None,
    };

    Config {
        uploader,
        session_key: "test this has to be over 32 bytes long".to_string(),
        gh_client_id: dotenv::var("GH_CLIENT_ID").unwrap_or_default(),
        gh_client_secret: dotenv::var("GH_CLIENT_SECRET").unwrap_or_default(),
        db_url: env("TEST_DATABASE_URL"),
        replica_db_url: None,
        env: Env::Test,
        max_upload_size: 3000,
        max_unpack_size: 2000,
        mirror: Replica::Primary,
        // When testing we route all API traffic over HTTP so we can
        // sniff/record it, but everywhere else we use https
        api_protocol: String::from("http"),
        publish_rate_limit: Default::default(),
        blocked_traffic: Default::default(),
        domain_name: "crates.io".into(),
        allowed_origins: Vec::new(),
    }
}

fn build_app(
    config: Config,
    proxy: Option<String>,
) -> (Arc<App>, conduit_middleware::MiddlewareBuilder) {
    let client = if let Some(proxy) = proxy {
        let mut builder = Client::builder();
        builder = builder
            .proxy(Proxy::all(&proxy).expect("Unable to configure proxy with the provided URL"));
        Some(builder.build().expect("TLS backend cannot be initialized"))
    } else {
        None
    };

    let app = App::new(config, client);
    assert_ok!(assert_ok!(app.primary_database.get()).begin_test_transaction());
    let app = Arc::new(app);
    let handler = cargo_registry::build_handler(Arc::clone(&app));
    (app, handler)
}

// Return the environment variable only if it has been defined
#[track_caller]
fn env(var: &str) -> String {
    match dotenv::var(var) {
        Ok(ref s) if s.is_empty() => panic!("environment variable `{}` must not be empty", var),
        Ok(s) => s,
        _ => panic!(
            "environment variable `{}` must be defined and valid unicode",
            var
        ),
    }
}

fn req(method: conduit::Method, path: &str) -> MockRequest {
    let mut request = MockRequest::new(method, path);
    request.header(header::USER_AGENT, "conduit-test");
    request
}

fn json<T>(r: &mut AppResponse) -> T
where
    for<'de> T: serde::Deserialize<'de>,
{
    use conduit::Body::*;

    let mut body = Body::empty();
    std::mem::swap(r.body_mut(), &mut body);
    let body: std::borrow::Cow<'static, [u8]> = match body {
        Static(slice) => slice.into(),
        Owned(vec) => vec.into(),
        File(_) => unimplemented!(),
    };

    let s = std::str::from_utf8(&body).unwrap();
    match serde_json::from_str(s) {
        Ok(t) => t,
        Err(e) => panic!("failed to decode: {:?}\n{}", e, s),
    }
}

static NEXT_GH_ID: AtomicUsize = AtomicUsize::new(0);

fn new_user(login: &str) -> NewUser<'_> {
    NewUser {
        gh_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        gh_login: login,
        name: None,
        gh_avatar: None,
        gh_access_token: Cow::Borrowed("some random token"),
    }
}

fn new_team(login: &str) -> NewTeam<'_> {
    NewTeam {
        org_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        github_id: NEXT_GH_ID.fetch_add(1, Ordering::SeqCst) as i32,
        login,
        name: None,
        avatar: None,
    }
}

fn add_team_to_crate(t: &Team, krate: &Crate, u: &User, conn: &PgConnection) -> QueryResult<()> {
    let crate_owner = CrateOwner {
        crate_id: krate.id,
        owner_id: t.id,
        created_by: u.id,
        owner_kind: 1, // Team owner kind is 1 according to owner.rs
        email_notifications: true,
    };

    diesel::insert_into(crate_owners::table)
        .values(&crate_owner)
        .on_conflict(crate_owners::table.primary_key())
        .do_update()
        .set(crate_owners::deleted.eq(false))
        .execute(conn)?;

    Ok(())
}

fn new_dependency(conn: &PgConnection, version: &Version, krate: &Crate) -> Dependency {
    use cargo_registry::schema::dependencies::dsl::*;
    use diesel::insert_into;

    insert_into(dependencies)
        .values((
            version_id.eq(version.id),
            crate_id.eq(krate.id),
            req.eq(">= 0"),
            optional.eq(false),
            default_features.eq(false),
            features.eq(Vec::<String>::new()),
        ))
        .get_result(conn)
        .unwrap()
}

fn new_category<'a>(category: &'a str, slug: &'a str, description: &'a str) -> NewCategory<'a> {
    NewCategory {
        category,
        slug,
        description,
    }
}

#[test]
fn multiple_live_references_to_the_same_connection_can_be_checked_out() {
    use std::ptr;

    let (app, _) = app();
    let conn1 = app.primary_database.get().unwrap();
    let conn2 = app.primary_database.get().unwrap();
    let conn1_ref: &PgConnection = &conn1;
    let conn2_ref: &PgConnection = &conn2;

    assert!(ptr::eq(conn1_ref, conn2_ref));
}
<|endoftext|>


<commit_before>use seed::prelude::*;
use std::{convert::TryFrom, fmt};
use chrono::prelude::*;

#[derive(Clone)]
pub struct Timestamp(DateTime<Local>);

impl Timestamp {
    pub fn format(&self, format: &str) -> String {
        self.0.format(format).to_string()
    }
}

impl fmt::Display for Timestamp {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl TryFrom<String> for Timestamp {
    type Error = String;

    fn try_from(string: String) -> Result<Self, Self::Error> {
        DateTime::parse_from_rfc3339(string.as_str())
            .map(|date_time| Timestamp(date_time.into()))
            .map_err(|parse_error| parse_error.to_string())
    }
}

/*pub fn view<Ms>(timestamp: &Timestamp) -> Node<Ms>{
    span![
        class!["date"],
        // "February 14, 2018"
        timestamp.format("%B %-d, %-Y")
    ]
}*/<commit_msg>Delete superflous timestamp.rs<commit_after><|endoftext|>


<commit_before>use {HashSet};
use std::collections::{HashMap, RingBuf, Deque};
use graph::{Graph, NodeIndex, Digraph};

/// Do a breadth-first search of the graph, returning the resulting breadth-
/// first forest.
fn bfs_forest<T, G: Graph<T>>(g: &G, start: NodeIndex) -> Digraph<NodeIndex> {
    let mut forest = Digraph::new();

    if g.num_nodes() == 0 {
        return forest;
    }

    let mut unvisited = HashSet::new();
    let mut visited = HashSet::new();
    let mut discovered = RingBuf::new();

    for i in g.node_indices() {
        unvisited.insert(i);
    }

    discovered.push_back((start, None));
    loop {
        match discovered.pop_front() {
            None => {
                if unvisited.len() == 0 {
                    break;
                } else {
                    let another = unvisited.iter().next().unwrap();
                    discovered.push_back((*another, None));
                    continue;
                }
            },
            Some((ind, parent)) => {
                forest.add_node(ind);
                if parent.is_some() {
                    forest.add_edge(parent.unwrap(), ind);
                }
                visited.insert(ind);
                unvisited.remove(&ind);

                for i in g.adj(ind) {
                    if !visited.contains(&i) {
                        discovered.push_back((i, Some(ind)));
                    }
                }
            }
        }
    }
    return forest;
}

<commit_msg>Change bfs to not traverse all the connected components.<commit_after>use {HashSet};
use std::collections::{HashMap, RingBuf, Deque};
use graph::{Graph, NodeIndex, Digraph};

/// Do a breadth-first search of the graph, returning the resulting breadth-
/// first tree (a tree on the connected component containing the stard node)
fn bfs_tree<T, G: Graph<T>>(g: &G, start: NodeIndex) -> Digraph<NodeIndex> {
    let mut tree = Digraph::new();

    if g.num_nodes() == 0 {
        return tree;
    }

    let mut visited = HashSet::new();
    let mut discovered = RingBuf::new();

    discovered.push_back((start, None));
    loop {
        match discovered.pop_front() {
            None => break,
            Some((ind, parent)) => {
                tree.add_node(ind);
                if parent.is_some() {
                    tree.add_edge(parent.unwrap(), ind);
                }
                visited.insert(ind);

                for i in g.adj(ind) {
                    if !visited.contains(&i) {
                        discovered.push_back((i, Some(ind)));
                    }
                }
            }
        }
    }
    return tree;
}

<|endoftext|>


<commit_before>use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
use collections::vec;
use core::cmp::max;
use core::mem;
use core::num::{Int, UnsignedInt};
use core::nonzero::NonZero;
use core::ptr;
use core::slice;
use core::usize;

#[derive(Debug, PartialEq, Eq)]
pub struct Extent {
    pub len: usize,
    pub cap: usize,
}

impl Copy for Extent {}

fn byte_length_of<A>(capacity: usize) -> usize {
    mem::size_of::<A>().checked_mul(capacity).expect("capacity overflow")
}

unsafe fn my_alloc<A>(capacity: usize) -> NonZero<*mut A> {
    if mem::size_of::<A>() == 0 {
        NonZero::new(EMPTY as *mut A)
    } else {
        let ptr = allocate(byte_length_of::<A>(capacity), mem::align_of::<A>());
        if ptr.is_null() { ::alloc::oom() }
        NonZero::new(ptr as *mut A)
    }
}

#[inline(never)]
unsafe fn alloc_or_realloc<A>(ptr: *mut A, old_size: usize, size: usize) -> NonZero<*mut A> {
    let ret =
        if old_size == 0 {
            allocate(size, mem::min_align_of::<A>())
        } else {
            reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::<A>())
        };

    if ret.is_null() { ::alloc::oom() }

    NonZero::new(ret as *mut A)
}

#[inline]
unsafe fn dealloc<A>(ptr: *mut A, cap: usize) {
    if mem::size_of::<A>() == 0 { return }

    deallocate(
        ptr as *mut u8,
        cap * mem::size_of::<A>(),
        mem::min_align_of::<A>());
}

#[must_use]
struct NewUpdate;

#[inline]
pub fn new_update(_: &[NewUpdate]) -> Extent {
    Extent { len: 0, cap: 0 }
}

#[must_use]
struct WithCapUpdate;

#[inline]
pub fn with_capacity_update(_: &[WithCapUpdate], is_boring: bool, new_cap: usize) -> Extent {
    let len = 0;
    let cap =
        if is_boring {
            usize::MAX
        } else {
            new_cap
        };

    Extent { len: len, cap: cap }
}

#[must_use]
struct FromRawPartsUpdate;

#[inline]
pub fn from_raw_parts_update(_: &[FromRawPartsUpdate], len: usize, cap: usize) -> Extent {
    Extent { len: len, cap: cap }
}

#[must_use]
struct FromRawBufsUpdate;

#[inline]
pub fn from_raw_bufs_update(_: &[FromRawBufsUpdate], elts: usize) -> Extent {
    Extent { len: elts, cap: elts }
}

#[must_use]
#[derive(Clone)]
struct ReserveCalc(usize);

#[inline]
pub fn calc_reserve_space(e: &Extent, additional: usize) -> Option<ReserveCalc> {
    if e.cap - e.len >= additional { return None }

    Some(ReserveCalc(
        e.len
        .checked_add(additional)
        .and_then(|base_len| base_len.checked_next_power_of_two())
        .expect("`usize` overflow")))
}

#[must_use]
struct ReserveUpdate;

#[inline]
pub fn reserve_update(_: &[ReserveUpdate], calc: ReserveCalc, e: &mut Extent) {
    e.cap = calc.0;
}

#[inline]
pub fn calc_reserve_exact_space(e: &Extent, additional: usize) -> Option<ReserveCalc> {
    if e.cap - e.len >= additional { return None }

    Some(ReserveCalc(
        e.len
        .checked_add(additional)
        .expect("`usize` overflow")))
}

#[must_use]
struct ShrinkToFitUpdate;

#[inline]
pub fn shrink_to_fit_update(_: &[ShrinkToFitUpdate], e: &mut Extent) {
    e.cap = e.len;
}

#[must_use]
struct TruncateUpdate;

#[inline]
pub fn truncate_update(_: &[TruncateUpdate], new_len: usize, e: &mut Extent) {
    e.len = new_len;
}

#[must_use]
struct InsertUpdate;

#[inline]
pub fn insert_update(_: &[InsertUpdate], calc: Option<ReserveCalc>, e: &mut Extent) {
    e.len += 1;
    calc.map(|calc| { e.cap = calc.0; });
}

#[must_use]
struct RemoveUpdate;

#[inline]
pub fn remove_update(_: &[RemoveUpdate], e: &mut Extent) {
    e.len -= 1;
}

#[must_use]
struct PushUpdate;

#[inline]
pub fn push_update(_: &[PushUpdate], e: &mut Extent) {
    if e.len == e.cap {
        e.cap = max(e.cap, 2) * 2;
    }

    e.len += 1;
}

#[must_use]
struct AppendUpdate;

#[inline]
pub fn append_update(_: &[AppendUpdate], e: &mut Extent, other_e: &mut Extent, space: Option<ReserveCalc>) {
    e.len += other_e.len;
    space.map(|calc| { e.cap = calc.0 });

    other_e.len = 0;
}

#[must_use]
struct PushAllUpdate;

#[inline]
pub fn push_all_update(_: &[PushAllUpdate], e: &mut Extent, len: usize, space: Option<ReserveCalc>) {
    e.len += len;
    space.map(|calc| { e.cap = calc.0 });
}

#[must_use]
#[derive(Debug)]
struct ExtendUpdate(Extent);

pub fn extend_update(extents: &[ExtendUpdate], e: &mut Extent) {
    let first_ext = extents[0].0;

    if extents.iter().any(|e| e.0 != first_ext) {
        // TODO: Clean up the excess elements added. This is a little tricky, since
        // the pointers need to be passed to extend_update, without slowing down
        // the fast path.
        panic!("`extend` called with iterators with unequal size: {:?}. Memory has been leaked!", extents);
    }

    *e = first_ext;
}

pub struct Unadorned<T> {
    ptr: NonZero<*mut T>,
}

unsafe impl<T: Send> Send for Unadorned<T> {}
unsafe impl<T: Sync> Sync for Unadorned<T> {}

impl<T> Unadorned<T> {
    pub fn is_boring(&self) -> bool {
        mem::size_of::<T>() == 0
    }

    #[inline]
    pub fn shallow_copy(&self) -> Self {
        Unadorned { ptr: self.ptr }
    }

    #[inline]
    pub unsafe fn new() -> (Unadorned<T>, NewUpdate) {
        (Unadorned {
            ptr: NonZero::new(EMPTY as *mut T),
        }, NewUpdate)
    }

    #[inline]
    pub unsafe fn with_capacity(cap: usize) -> (Unadorned<T>, WithCapUpdate) {
        (Unadorned {
            ptr: my_alloc::<T>(cap),
        }, WithCapUpdate)
    }

    #[inline]
    pub unsafe fn from_raw_parts(ptr: *mut T) -> (Unadorned<T>, FromRawPartsUpdate) {
        assert!(!ptr.is_null());
        (Unadorned {
            ptr: NonZero::new(ptr),
        }, FromRawPartsUpdate)
    }

    #[inline]
    pub unsafe fn as_vec(&self, e: &Extent) -> Vec<T> {
        Vec::from_raw_parts(*self.ptr, e.len, e.cap)
    }

    #[inline]
    pub fn as_ptr(&self) -> *const T {
        *self.ptr as *const T
    }

    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut T {
        *self.ptr
    }

    pub unsafe fn from_raw_bufs(src: *const T, elts: usize) -> (Unadorned<T>, FromRawBufsUpdate) {
        let dst = my_alloc::<T>(elts);
        ptr::copy_nonoverlapping_memory(*dst, src, elts);
        (Unadorned {
            ptr: dst,
        }, FromRawBufsUpdate)
    }

    #[inline]
    pub unsafe fn reserve(&mut self, e: &Extent, space_needed: &ReserveCalc) -> ReserveUpdate {
        let old_cap = e.cap;
        let new_cap = space_needed.0;

        if self.is_boring() { return ReserveUpdate }

        let size = byte_length_of::<T>(new_cap);
        self.ptr = alloc_or_realloc(*self.ptr, old_cap * mem::size_of::<T>(), size);

        ReserveUpdate
    }

    pub unsafe fn shrink_to_fit(&mut self, e: &Extent) -> ShrinkToFitUpdate {
        if self.is_boring() { return ShrinkToFitUpdate }

        if e.len == 0 {
            if e.cap != 0 {
                dealloc(*self.ptr, e.cap);
            }
        } else {
            let new_ptr =
                reallocate(*self.ptr as *mut u8,
                           e.cap * mem::size_of::<T>(),
                           e.len * mem::size_of::<T>(),
                           mem::min_align_of::<T>()) as *mut T;
            if new_ptr.is_null() { ::alloc::oom() }
            self.ptr = NonZero::new(new_ptr);
        }

        ShrinkToFitUpdate
    }

    pub unsafe fn truncate(&mut self, len: usize, e: &Extent) -> TruncateUpdate {
        if self.is_boring() { return TruncateUpdate }

        let mut real_len = e.len;

        while len < real_len {
            real_len -= 1;
            ptr::read(self.ptr.offset(real_len as isize));
        }

        TruncateUpdate
    }

    #[inline]
    pub unsafe fn as_slice<'a>(&'a self, len: usize) -> &'a [T] {
        let p: &'a *const T = mem::transmute(&*self.ptr);
        slice::from_raw_buf(p, len)
    }

    #[inline]
    pub unsafe fn as_mut_slice<'a>(&'a mut self, len: usize) -> &'a mut [T] {
        slice::from_raw_mut_buf(&*self.ptr, len)
    }

    #[inline]
    pub unsafe fn into_iter(self, e: &Extent) -> vec::IntoIter<T> {
        let r = Vec::from_raw_parts(*self.ptr, e.len, e.cap);
        r.into_iter()
    }

    pub unsafe fn insert(&mut self,
                  index: usize, x: T,
                  e: &Extent, space_needed: &Option<ReserveCalc>) -> InsertUpdate {
        let _ = space_needed.as_ref().map(|space| self.reserve(e, space));

        let p = self.ptr.offset(index as isize);
        ptr::copy_memory(p.offset(1), &*p, e.len - index);
        ptr::write(&mut *p, x);

        InsertUpdate
    }

    pub unsafe fn remove(&mut self, index: usize, e: &Extent) -> (T, RemoveUpdate) {
        let ptr = self.ptr.offset(index as isize);
        let ret = ptr::read(ptr);
        ptr::copy_memory(ptr, &*ptr.offset(1), e.len - index - 1);
        (ret, RemoveUpdate)
    }

    unsafe fn make_room_for_one(&mut self, e: &Extent) {
        if self.is_boring() { return }

        let old_size = e.cap * mem::size_of::<T>();
        let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
        if old_size > size { panic!("capacity overflow") }
        self.ptr = alloc_or_realloc(*self.ptr, old_size, size);
    }

    #[inline]
    pub unsafe fn push(&mut self, value: T, e: &Extent) -> PushUpdate {
        if e.len == e.cap {
            self.make_room_for_one(e);
        }

        ptr::write(self.ptr.offset(e.len as isize), value);
        PushUpdate
    }

    #[inline]
    pub unsafe fn append(&mut self, self_e: &Extent, other: &Self, other_e: &Extent, space: &Option<ReserveCalc>) -> AppendUpdate {
        space.as_ref().map(|space| self.reserve(self_e, space));
        ptr::copy_nonoverlapping_memory(*self.ptr, *other.ptr, other_e.len);

        AppendUpdate
    }

    pub unsafe fn extend<I: Iterator<Item=T>>(&mut self, e: &Extent, space: &Option<ReserveCalc>, i: I) -> ExtendUpdate {
        let mut this_extent: Extent = *e;

        space.as_ref().map(|space| {
            let ru = self.reserve(e, space);
            reserve_update(&[ru], (*space).clone(), &mut this_extent);
        });

        for x in i {
            let u = self.push(x, &this_extent);
            push_update(&[u], &mut this_extent);
        }

        ExtendUpdate(this_extent)
    }

    pub unsafe fn drop(&self, e: &Extent) {
        for x in self.as_slice(e.len) {
            drop(ptr::read(x));
        }
        dealloc(*self.ptr, e.cap);
    }
}

impl<T: Clone> Unadorned<T> {
    #[inline]
    pub unsafe fn push_all(&mut self, x: &[T], e: &Extent, space: &Option<ReserveCalc>) -> PushAllUpdate {
        space.as_ref().map(|space| self.reserve(e, space));

        let mut len = e.len;

        for i in range(0, x.len()) {
            // LLVM is easily confused. This is carefully constructed such that
            // Copy types get a memcpy.
            ptr::write(self.ptr.offset(len as isize), x.get_unchecked(i).clone());
            len += 1;
        }

        PushAllUpdate
    }
}
<commit_msg>fixed warnings<commit_after>use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
use collections::vec;
use core::cmp::max;
use core::mem;
use core::num::{Int, UnsignedInt};
use core::nonzero::NonZero;
use core::ptr;
use core::slice;
use core::usize;

#[derive(Debug, PartialEq, Eq)]
pub struct Extent {
    pub len: usize,
    pub cap: usize,
}

impl Copy for Extent {}

fn byte_length_of<A>(capacity: usize) -> usize {
    mem::size_of::<A>().checked_mul(capacity).expect("capacity overflow")
}

unsafe fn my_alloc<A>(capacity: usize) -> NonZero<*mut A> {
    if mem::size_of::<A>() == 0 {
        NonZero::new(EMPTY as *mut A)
    } else {
        let ptr = allocate(byte_length_of::<A>(capacity), mem::align_of::<A>());
        if ptr.is_null() { ::alloc::oom() }
        NonZero::new(ptr as *mut A)
    }
}

#[inline(never)]
unsafe fn alloc_or_realloc<A>(ptr: *mut A, old_size: usize, size: usize) -> NonZero<*mut A> {
    let ret =
        if old_size == 0 {
            allocate(size, mem::min_align_of::<A>())
        } else {
            reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::<A>())
        };

    if ret.is_null() { ::alloc::oom() }

    NonZero::new(ret as *mut A)
}

#[inline]
unsafe fn dealloc<A>(ptr: *mut A, cap: usize) {
    if mem::size_of::<A>() == 0 { return }

    deallocate(
        ptr as *mut u8,
        cap * mem::size_of::<A>(),
        mem::min_align_of::<A>());
}

#[must_use]
struct NewUpdate;

#[inline]
pub fn new_update(_: &[NewUpdate]) -> Extent {
    Extent { len: 0, cap: 0 }
}

#[must_use]
struct WithCapUpdate;

#[inline]
pub fn with_capacity_update(_: &[WithCapUpdate], is_boring: bool, new_cap: usize) -> Extent {
    let len = 0;
    let cap =
        if is_boring {
            usize::MAX
        } else {
            new_cap
        };

    Extent { len: len, cap: cap }
}

#[must_use]
struct FromRawPartsUpdate;

#[inline]
pub fn from_raw_parts_update(_: &[FromRawPartsUpdate], len: usize, cap: usize) -> Extent {
    Extent { len: len, cap: cap }
}

#[must_use]
struct FromRawBufsUpdate;

#[inline]
pub fn from_raw_bufs_update(_: &[FromRawBufsUpdate], elts: usize) -> Extent {
    Extent { len: elts, cap: elts }
}

#[must_use]
#[derive(Clone)]
struct ReserveCalc(usize);

#[inline]
pub fn calc_reserve_space(e: &Extent, additional: usize) -> Option<ReserveCalc> {
    if e.cap - e.len >= additional { return None }

    Some(ReserveCalc(
        e.len
        .checked_add(additional)
        .and_then(|base_len| base_len.checked_next_power_of_two())
        .expect("`usize` overflow")))
}

#[must_use]
struct ReserveUpdate;

#[inline]
pub fn reserve_update(_: &[ReserveUpdate], calc: ReserveCalc, e: &mut Extent) {
    e.cap = calc.0;
}

#[inline]
pub fn calc_reserve_exact_space(e: &Extent, additional: usize) -> Option<ReserveCalc> {
    if e.cap - e.len >= additional { return None }

    Some(ReserveCalc(
        e.len
        .checked_add(additional)
        .expect("`usize` overflow")))
}

#[must_use]
struct ShrinkToFitUpdate;

#[inline]
pub fn shrink_to_fit_update(_: &[ShrinkToFitUpdate], e: &mut Extent) {
    e.cap = e.len;
}

#[must_use]
struct TruncateUpdate;

#[inline]
pub fn truncate_update(_: &[TruncateUpdate], new_len: usize, e: &mut Extent) {
    e.len = new_len;
}

#[must_use]
struct InsertUpdate;

#[inline]
pub fn insert_update(_: &[InsertUpdate], calc: Option<ReserveCalc>, e: &mut Extent) {
    e.len += 1;
    calc.map(|calc| { e.cap = calc.0; });
}

#[must_use]
struct RemoveUpdate;

#[inline]
pub fn remove_update(_: &[RemoveUpdate], e: &mut Extent) {
    e.len -= 1;
}

#[must_use]
struct PushUpdate;

#[inline]
pub fn push_update(_: &[PushUpdate], e: &mut Extent) {
    if e.len == e.cap {
        e.cap = max(e.cap, 2) * 2;
    }

    e.len += 1;
}

#[must_use]
struct AppendUpdate;

#[inline]
pub fn append_update(_: &[AppendUpdate], e: &mut Extent, other_e: &mut Extent, space: Option<ReserveCalc>) {
    e.len += other_e.len;
    space.map(|calc| { e.cap = calc.0 });

    other_e.len = 0;
}

#[must_use]
struct PushAllUpdate;

#[inline]
pub fn push_all_update(_: &[PushAllUpdate], e: &mut Extent, len: usize, space: Option<ReserveCalc>) {
    e.len += len;
    space.map(|calc| { e.cap = calc.0 });
}

#[must_use]
#[derive(Debug)]
struct ExtendUpdate(Extent);

pub fn extend_update(extents: &[ExtendUpdate], e: &mut Extent) {
    let first_ext = extents[0].0;

    if extents.iter().any(|e| e.0 != first_ext) {
        // TODO: Clean up the excess elements added. This is a little tricky, since
        // the pointers need to be passed to extend_update, without slowing down
        // the fast path.
        panic!("`extend` called with iterators with unequal size: {:?}. Memory has been leaked!", extents);
    }

    *e = first_ext;
}

pub struct Unadorned<T> {
    ptr: NonZero<*mut T>,
}

unsafe impl<T: Send> Send for Unadorned<T> {}
unsafe impl<T: Sync> Sync for Unadorned<T> {}

impl<T> Unadorned<T> {
    pub fn is_boring(&self) -> bool {
        mem::size_of::<T>() == 0
    }

    #[inline]
    pub fn shallow_copy(&self) -> Self {
        Unadorned { ptr: self.ptr }
    }

    #[inline]
    pub unsafe fn new() -> (Unadorned<T>, NewUpdate) {
        (Unadorned {
            ptr: NonZero::new(EMPTY as *mut T),
        }, NewUpdate)
    }

    #[inline]
    pub unsafe fn with_capacity(cap: usize) -> (Unadorned<T>, WithCapUpdate) {
        (Unadorned {
            ptr: my_alloc::<T>(cap),
        }, WithCapUpdate)
    }

    #[inline]
    pub unsafe fn from_raw_parts(ptr: *mut T) -> (Unadorned<T>, FromRawPartsUpdate) {
        assert!(!ptr.is_null());
        (Unadorned {
            ptr: NonZero::new(ptr),
        }, FromRawPartsUpdate)
    }

    #[inline]
    pub unsafe fn as_vec(&self, e: &Extent) -> Vec<T> {
        Vec::from_raw_parts(*self.ptr, e.len, e.cap)
    }

    #[inline]
    pub fn as_ptr(&self) -> *const T {
        *self.ptr as *const T
    }

    #[inline]
    pub fn as_mut_ptr(&mut self) -> *mut T {
        *self.ptr
    }

    pub unsafe fn from_raw_bufs(src: *const T, elts: usize) -> (Unadorned<T>, FromRawBufsUpdate) {
        let dst = my_alloc::<T>(elts);
        ptr::copy_nonoverlapping_memory(*dst, src, elts);
        (Unadorned {
            ptr: dst,
        }, FromRawBufsUpdate)
    }

    #[inline]
    pub unsafe fn reserve(&mut self, e: &Extent, space_needed: &ReserveCalc) -> ReserveUpdate {
        let old_cap = e.cap;
        let new_cap = space_needed.0;

        if self.is_boring() { return ReserveUpdate }

        let size = byte_length_of::<T>(new_cap);
        self.ptr = alloc_or_realloc(*self.ptr, old_cap * mem::size_of::<T>(), size);

        ReserveUpdate
    }

    pub unsafe fn shrink_to_fit(&mut self, e: &Extent) -> ShrinkToFitUpdate {
        if self.is_boring() { return ShrinkToFitUpdate }

        if e.len == 0 {
            if e.cap != 0 {
                dealloc(*self.ptr, e.cap);
            }
        } else {
            let new_ptr =
                reallocate(*self.ptr as *mut u8,
                           e.cap * mem::size_of::<T>(),
                           e.len * mem::size_of::<T>(),
                           mem::min_align_of::<T>()) as *mut T;
            if new_ptr.is_null() { ::alloc::oom() }
            self.ptr = NonZero::new(new_ptr);
        }

        ShrinkToFitUpdate
    }

    pub unsafe fn truncate(&mut self, len: usize, e: &Extent) -> TruncateUpdate {
        if self.is_boring() { return TruncateUpdate }

        let mut real_len = e.len;

        while len < real_len {
            real_len -= 1;
            ptr::read(self.ptr.offset(real_len as isize));
        }

        TruncateUpdate
    }

    #[inline]
    pub unsafe fn as_slice<'a>(&'a self, len: usize) -> &'a [T] {
        let p: &'a *const T = mem::transmute(&*self.ptr);
        slice::from_raw_parts(*p, len)
    }

    #[inline]
    pub unsafe fn as_mut_slice<'a>(&'a mut self, len: usize) -> &'a mut [T] {
        slice::from_raw_parts_mut(*self.ptr, len)
    }

    #[inline]
    pub unsafe fn into_iter(self, e: &Extent) -> vec::IntoIter<T> {
        let r = Vec::from_raw_parts(*self.ptr, e.len, e.cap);
        r.into_iter()
    }

    pub unsafe fn insert(&mut self,
                  index: usize, x: T,
                  e: &Extent, space_needed: &Option<ReserveCalc>) -> InsertUpdate {
        let _ = space_needed.as_ref().map(|space| self.reserve(e, space));

        let p = self.ptr.offset(index as isize);
        ptr::copy_memory(p.offset(1), &*p, e.len - index);
        ptr::write(&mut *p, x);

        InsertUpdate
    }

    pub unsafe fn remove(&mut self, index: usize, e: &Extent) -> (T, RemoveUpdate) {
        let ptr = self.ptr.offset(index as isize);
        let ret = ptr::read(ptr);
        ptr::copy_memory(ptr, &*ptr.offset(1), e.len - index - 1);
        (ret, RemoveUpdate)
    }

    unsafe fn make_room_for_one(&mut self, e: &Extent) {
        if self.is_boring() { return }

        let old_size = e.cap * mem::size_of::<T>();
        let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
        if old_size > size { panic!("capacity overflow") }
        self.ptr = alloc_or_realloc(*self.ptr, old_size, size);
    }

    #[inline]
    pub unsafe fn push(&mut self, value: T, e: &Extent) -> PushUpdate {
        if e.len == e.cap {
            self.make_room_for_one(e);
        }

        ptr::write(self.ptr.offset(e.len as isize), value);
        PushUpdate
    }

    #[inline]
    pub unsafe fn append(&mut self, self_e: &Extent, other: &Self, other_e: &Extent, space: &Option<ReserveCalc>) -> AppendUpdate {
        space.as_ref().map(|space| self.reserve(self_e, space));
        ptr::copy_nonoverlapping_memory(*self.ptr, *other.ptr, other_e.len);

        AppendUpdate
    }

    pub unsafe fn extend<I: Iterator<Item=T>>(&mut self, e: &Extent, space: &Option<ReserveCalc>, i: I) -> ExtendUpdate {
        let mut this_extent: Extent = *e;

        space.as_ref().map(|space| {
            let ru = self.reserve(e, space);
            reserve_update(&[ru], (*space).clone(), &mut this_extent);
        });

        for x in i {
            let u = self.push(x, &this_extent);
            push_update(&[u], &mut this_extent);
        }

        ExtendUpdate(this_extent)
    }

    pub unsafe fn drop(&self, e: &Extent) {
        for x in self.as_slice(e.len) {
            drop(ptr::read(x));
        }
        dealloc(*self.ptr, e.cap);
    }
}

impl<T: Clone> Unadorned<T> {
    #[inline]
    pub unsafe fn push_all(&mut self, x: &[T], e: &Extent, space: &Option<ReserveCalc>) -> PushAllUpdate {
        space.as_ref().map(|space| self.reserve(e, space));

        let mut len = e.len;

        for i in range(0, x.len()) {
            // LLVM is easily confused. This is carefully constructed such that
            // Copy types get a memcpy.
            ptr::write(self.ptr.offset(len as isize), x.get_unchecked(i).clone());
            len += 1;
        }

        PushAllUpdate
    }
}
<|endoftext|>


<commit_before>use indexmap::IndexSet;
use std::ops::{Deref, DerefMut};
use vec::Vec;

use common::DebugStrOffset;
use write::{Result, Section, SectionId, Writer};

/// An identifier for a string in a `StringTable.`
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StringId(usize);

/// A table of strings that will be stored in a `.debug_str` section.
// Requirements:
// - values are `[u8]`, null bytes are not allowed
// - insertion returns a fixed id
// - inserting a duplicate returns the id of the existing value
// - able to convert an id to a section offset
// Optional?
// - able to get an existing value given an id
//
// Limitations of current implementation (using IndexSet):
// - inserting requires either an allocation for duplicates,
//   or a double lookup for non-duplicates
// - doesn't preserve offsets when updating an existing `.debug_str` section
//
// Possible changes:
// - calculate offsets as we add values, and use that as the id.
//   This would avoid the need for DebugStrOffsets but would make it
//   hard to implement `get`.
#[derive(Debug, Default)]
pub struct StringTable {
    strings: IndexSet<Vec<u8>>,
}

impl StringTable {
    /// Add a string to the string table and return its id.
    ///
    /// If the string already exists, then return the id of the existing string.
    ///
    /// # Panics
    ///
    /// Panics if `bytes` contains a null byte.
    pub fn add<T>(&mut self, bytes: T) -> StringId
    where
        T: Into<Vec<u8>>,
    {
        let bytes = bytes.into();
        assert!(!bytes.contains(&0));
        let (index, _) = self.strings.insert_full(bytes);
        StringId(index)
    }

    /// Return the number of strings in the table.
    #[inline]
    pub fn count(&self) -> usize {
        self.strings.len()
    }

    /// Get a reference to a string in the table.
    ///
    /// # Panics
    ///
    /// Panics if `id` is invalid.
    pub fn get(&self, id: StringId) -> &[u8] {
        self.strings.get_index(id.0).map(Vec::as_slice).unwrap()
    }

    /// Write the string table to the `.debug_str` section.
    ///
    /// Returns the offsets at which the strings are written.
    pub fn write<W: Writer>(&self, w: &mut DebugStr<W>) -> Result<DebugStrOffsets> {
        let mut offsets = Vec::new();
        for bytes in self.strings.iter() {
            offsets.push(w.offset());
            w.write(bytes)?;
            w.write_u8(0)?;
        }

        Ok(DebugStrOffsets { offsets })
    }
}

define_section!(DebugStr, DebugStrOffset, "A writable `.debug_str` section.");

define_offsets!(
    DebugStrOffsets: StringId => DebugStrOffset,
    "The section offsets of all strings within a `.debug_str` section."
);

#[cfg(test)]
mod tests {
    use super::*;
    use read;
    use write::EndianVec;
    use LittleEndian;

    #[test]
    fn test_string_table() {
        let mut strings = StringTable::default();
        assert_eq!(strings.count(), 0);
        let id1 = strings.add(&b"one"[..]);
        let id2 = strings.add(&b"two"[..]);
        assert_eq!(strings.add(&b"one"[..]), id1);
        assert_eq!(strings.add(&b"two"[..]), id2);
        assert_eq!(strings.get(id1), &b"one"[..]);
        assert_eq!(strings.get(id2), &b"two"[..]);
        assert_eq!(strings.count(), 2);

        let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
        let offsets = strings.write(&mut debug_str).unwrap();
        assert_eq!(debug_str.slice(), b"one\0two\0");
        assert_eq!(offsets.get(id1), DebugStrOffset(0));
        assert_eq!(offsets.get(id2), DebugStrOffset(4));
        assert_eq!(offsets.count(), 2);
    }

    #[test]
    fn test_string_table_read() {
        let mut strings = StringTable::default();
        let id1 = strings.add(&b"one"[..]);
        let id2 = strings.add(&b"two"[..]);

        let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
        let offsets = strings.write(&mut debug_str).unwrap();

        let read_debug_str = read::DebugStr::new(debug_str.slice(), LittleEndian);
        let str1 = read_debug_str.get_str(offsets.get(id1)).unwrap();
        let str2 = read_debug_str.get_str(offsets.get(id2)).unwrap();
        assert_eq!(str1.slice(), &b"one"[..]);
        assert_eq!(str2.slice(), &b"two"[..]);
    }
}
<commit_msg>write/str: add define_string_table!()<commit_after>use indexmap::IndexSet;
use std::ops::{Deref, DerefMut};
use vec::Vec;

use common::DebugStrOffset;
use write::{Result, Section, SectionId, Writer};

// Requirements:
// - values are `[u8]`, null bytes are not allowed
// - insertion returns a fixed id
// - inserting a duplicate returns the id of the existing value
// - able to convert an id to a section offset
// Optional?
// - able to get an existing value given an id
//
// Limitations of current implementation (using IndexSet):
// - inserting requires either an allocation for duplicates,
//   or a double lookup for non-duplicates
// - doesn't preserve offsets when updating an existing `.debug_str` section
//
// Possible changes:
// - calculate offsets as we add values, and use that as the id.
//   This would avoid the need for DebugStrOffsets but would make it
//   hard to implement `get`.
macro_rules! define_string_table {
    ($name:ident, $id:ident, $section:ident, $offsets:ident, $docs:expr) => {
        #[doc=$docs]
        #[derive(Debug, Default)]
        pub struct $name {
            strings: IndexSet<Vec<u8>>,
        }

        impl $name {
            /// Add a string to the string table and return its id.
            ///
            /// If the string already exists, then return the id of the existing string.
            ///
            /// # Panics
            ///
            /// Panics if `bytes` contains a null byte.
            pub fn add<T>(&mut self, bytes: T) -> $id
            where
                T: Into<Vec<u8>>,
            {
                let bytes = bytes.into();
                assert!(!bytes.contains(&0));
                let (index, _) = self.strings.insert_full(bytes);
                $id(index)
            }

            /// Return the number of strings in the table.
            #[inline]
            pub fn count(&self) -> usize {
                self.strings.len()
            }

            /// Get a reference to a string in the table.
            ///
            /// # Panics
            ///
            /// Panics if `id` is invalid.
            pub fn get(&self, id: $id) -> &[u8] {
                self.strings.get_index(id.0).map(Vec::as_slice).unwrap()
            }

            /// Write the string table to the `.debug_str` section.
            ///
            /// Returns the offsets at which the strings are written.
            pub fn write<W: Writer>(&self, w: &mut $section<W>) -> Result<$offsets> {
                let mut offsets = Vec::new();
                for bytes in self.strings.iter() {
                    offsets.push(w.offset());
                    w.write(bytes)?;
                    w.write_u8(0)?;
                }

                Ok($offsets { offsets })
            }
        }
    };
}

/// An identifier for a string in a `StringTable`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct StringId(usize);

define_string_table!(
    StringTable,
    StringId,
    DebugStr,
    DebugStrOffsets,
    "A table of strings that will be stored in a `.debug_str` section."
);

define_section!(DebugStr, DebugStrOffset, "A writable `.debug_str` section.");

define_offsets!(
    DebugStrOffsets: StringId => DebugStrOffset,
    "The section offsets of all strings within a `.debug_str` section."
);

#[cfg(test)]
mod tests {
    use super::*;
    use read;
    use write::EndianVec;
    use LittleEndian;

    #[test]
    fn test_string_table() {
        let mut strings = StringTable::default();
        assert_eq!(strings.count(), 0);
        let id1 = strings.add(&b"one"[..]);
        let id2 = strings.add(&b"two"[..]);
        assert_eq!(strings.add(&b"one"[..]), id1);
        assert_eq!(strings.add(&b"two"[..]), id2);
        assert_eq!(strings.get(id1), &b"one"[..]);
        assert_eq!(strings.get(id2), &b"two"[..]);
        assert_eq!(strings.count(), 2);

        let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
        let offsets = strings.write(&mut debug_str).unwrap();
        assert_eq!(debug_str.slice(), b"one\0two\0");
        assert_eq!(offsets.get(id1), DebugStrOffset(0));
        assert_eq!(offsets.get(id2), DebugStrOffset(4));
        assert_eq!(offsets.count(), 2);
    }

    #[test]
    fn test_string_table_read() {
        let mut strings = StringTable::default();
        let id1 = strings.add(&b"one"[..]);
        let id2 = strings.add(&b"two"[..]);

        let mut debug_str = DebugStr::from(EndianVec::new(LittleEndian));
        let offsets = strings.write(&mut debug_str).unwrap();

        let read_debug_str = read::DebugStr::new(debug_str.slice(), LittleEndian);
        let str1 = read_debug_str.get_str(offsets.get(id1)).unwrap();
        let str2 = read_debug_str.get_str(offsets.get(id2)).unwrap();
        assert_eq!(str1.slice(), &b"one"[..]);
        assert_eq!(str2.slice(), &b"two"[..]);
    }
}
<|endoftext|>


<commit_before>#[link(name = "fibonacci", vers = "1.0", author = "eliovir")];
#[crate_type = "lib"];
/**
 * Compute fibonacci.
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */

extern mod extra;
/**
* Calcule les elements de la suite de Fibonnaci.
*
* REGLE RG024 Le projet permet de calculer les membres de la Suite de
* Fibonacci.
*
* REGLE RG024.1 : f(1) = 1
* REGLE RG024.2 : f(2) = 1
*
* REGLE RG024.3 : f(n) = f(n-1) + f(n-2) si n > 2
*
* REGLE RG024.4 : il n'est pas possible de calculer la valeur de la Suite
* de Fibonacci pour un rang negatif.
*
* REGLE RG024.5 : le calcul de n'importe quel element de la Suite de
* Fibonacci doit s'effectuer en moins de deux secondes.
*
* REGLE RG024.6 : le calcul de n'importe quel element de la Suite de
* Fibonacci, pour un rang inferieur a 50, doit s'effectuer en moins d'une
* seconde.
*
* @param n le rang pour lequel on calcule le membre.
* @return Le membre de rang n dans la Suite.
*/
fn fibonacci(n: int) -> uint {
	if n < 0 {
		fail!(fmt!("%d is negative!", n));
	}
	match n {
		0     => fail!("zero is not a right argument to fibonacci()!"),
		1 | 2 => 1,
		3     => 2,
		/*
		50    => 12586269025,
		*/
		_     => fibonacci(n - 1) + fibonacci(n - 2)
	}
}
/*
#[cfg(test)]
mod tests {
}
*/
fn RG024_x(n: int, expected: uint) {
	// println(fmt!("RG024_x(%d, %u)", n, expected));
	let found = fibonacci(n);
	assert!(expected == found);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.1 : f(1) = 1
 */
#[test]
fn RG024_1() {
	RG024_x(1, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.2 : f(2) = 1
 */
#[test]
fn RG024_2() {
	RG024_x(2, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.3.a : f(3) = 2
 */
#[test]
fn RG024_3_a() {
	RG024_x(3, 2);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.4.a : il n'est pas possible de calculer la valeur de la Suite
 * de Fibonacci pour un rang negatif ou nul.
 */
#[test]
#[should_fail]
fn RG024_4_a() {
	fibonacci(-1);
	fibonacci(0);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.5 : f(55) = 139583862445
 */
#[test]
fn RG024_5() {
	/*RG024_x(55, 139583862445);*/
	RG024_x(30, 832040);
}
#[bench]
fn bench_fibonacci_20(b: &mut extra::test::BenchHarness) {
	do b.iter {
		fibonacci(20);
	}
}
<commit_msg>libfibonacci.rs : add doc attributes<commit_after>#[link(name = "fibonacci", vers = "1.0", author = "eliovir")];
#[crate_type = "lib"];
#[license = "MIT"];
#[desc = "Fibonacci library" ];
#[comment = "Example of library: compute Fibonacci"];
/**
 * Compute fibonacci.
 *
 * @license MIT license <http://www.opensource.org/licenses/mit-license.php>
 */

extern mod extra;
/**
* Calcule les elements de la suite de Fibonnaci.
*
* REGLE RG024 Le projet permet de calculer les membres de la Suite de
* Fibonacci.
*
* REGLE RG024.1 : f(1) = 1
* REGLE RG024.2 : f(2) = 1
*
* REGLE RG024.3 : f(n) = f(n-1) + f(n-2) si n > 2
*
* REGLE RG024.4 : il n'est pas possible de calculer la valeur de la Suite
* de Fibonacci pour un rang negatif.
*
* REGLE RG024.5 : le calcul de n'importe quel element de la Suite de
* Fibonacci doit s'effectuer en moins de deux secondes.
*
* REGLE RG024.6 : le calcul de n'importe quel element de la Suite de
* Fibonacci, pour un rang inferieur a 50, doit s'effectuer en moins d'une
* seconde.
*
* @param n le rang pour lequel on calcule le membre.
* @return Le membre de rang n dans la Suite.
*/
fn fibonacci(n: int) -> uint {
	if n < 0 {
		fail!(fmt!("%d is negative!", n));
	}
	match n {
		0     => fail!("zero is not a right argument to fibonacci()!"),
		1 | 2 => 1,
		3     => 2,
		/*
		50    => 12586269025,
		*/
		_     => fibonacci(n - 1) + fibonacci(n - 2)
	}
}
/*
#[cfg(test)]
mod tests {
}
*/
fn RG024_x(n: int, expected: uint) {
	// println(fmt!("RG024_x(%d, %u)", n, expected));
	let found = fibonacci(n);
	assert!(expected == found);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.1 : f(1) = 1
 */
#[test]
fn RG024_1() {
	RG024_x(1, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.2 : f(2) = 1
 */
#[test]
fn RG024_2() {
	RG024_x(2, 1);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.3.a : f(3) = 2
 */
#[test]
fn RG024_3_a() {
	RG024_x(3, 2);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.4.a : il n'est pas possible de calculer la valeur de la Suite
 * de Fibonacci pour un rang negatif ou nul.
 */
#[test]
#[should_fail]
fn RG024_4_a() {
	fibonacci(-1);
	fibonacci(0);
}
/**
 * Test du calcul de la suite de Fibonnaci.
 *
 * REGLE RG024.5 : f(55) = 139583862445
 */
#[test]
fn RG024_5() {
	/*RG024_x(55, 139583862445);*/
	RG024_x(30, 832040);
}
#[bench]
fn bench_fibonacci_20(b: &mut extra::test::BenchHarness) {
	do b.iter {
		fibonacci(20);
	}
}
<|endoftext|>


<commit_before>use ::cairo;
use ::glib_sys;

use glib::translate::*;
use cairo::MatrixTrait;

/* Keep this in sync with ../../rsvg-private.h:RsvgBbox */
#[repr(C)]
pub struct RsvgBbox {
    pub rect:   cairo::Rectangle,
    pub affine: cairo::Matrix,
    virgin:     glib_sys::gboolean
}

impl RsvgBbox {
    pub fn is_virgin (&self) -> bool {
        from_glib (self.virgin)
    }
}

#[no_mangle]
pub extern fn rsvg_bbox_init (raw_bbox: *mut RsvgBbox, raw_matrix: *const cairo::Matrix) {
    assert! (!raw_bbox.is_null ());
    assert! (!raw_matrix.is_null ());

    let bbox: &mut RsvgBbox = unsafe { &mut (*raw_bbox) };

    bbox.virgin = true.to_glib ();
    bbox.affine = unsafe { *raw_matrix };
}

#[no_mangle]
pub extern fn rsvg_bbox_insert (raw_dst: *mut RsvgBbox, raw_src: *const RsvgBbox) {
    assert! (!raw_dst.is_null ());
    assert! (!raw_src.is_null ());

    let dst: &mut RsvgBbox = unsafe { &mut (*raw_dst) };
    let src: &RsvgBbox = unsafe { &*raw_src };

    if src.is_virgin () {
        return;
    }

    let (mut xmin, mut ymin, mut xmax, mut ymax) = if !dst.is_virgin () {
        (dst.rect.y, dst.rect.y, (dst.rect.x + dst.rect.width), (dst.rect.y + dst.rect.height))
    } else {
        (0.0, 0.0, 0.0, 0.0)
    };

    let mut affine = dst.affine;

    affine.invert (); // this will panic!() if it's not invertible... should we check on our own?
    affine = cairo::Matrix::multiply (&src.affine, &affine);

    /* This is a trick.  We want to transform each of the corners of
     * the rectangle defined by src.rect with the affine
     * transformation, and get the bounding box of all the four
     * resulting points.  The modulus and division accomplish this by
     * running through all the combinations of adding or not adding
     * the width/height to the first point src.rect.(x, y).
     */
    for i in 0..4 {
        let rx: f64 = src.rect.x + src.rect.width * f64::from(i % 2);
        let ry: f64 = src.rect.y + src.rect.height * f64::from(i / 2);
        let x: f64  = affine.xx * rx + affine.xy * ry + affine.x0;
        let y: f64  = affine.yx * rx + affine.yy * ry + affine.y0;

        if dst.is_virgin () {
            xmin = x;
            xmax = x;
            ymin = y;
            ymax = y;
            dst.virgin = false.to_glib ();
        } else {
            if x < xmin { xmin = x; }
            if x > xmax { xmax = x; }
            if y < ymin { ymin = y; }
            if y > ymax { ymax = y; }
        }
    }

    dst.rect.x = xmin;
    dst.rect.y = ymin;
    dst.rect.width = xmax - xmin;
    dst.rect.height = ymax - ymin;
}

#[no_mangle]
pub extern fn rsvg_bbox_clip (raw_dst: *mut RsvgBbox, raw_src: *const RsvgBbox) {
    assert! (!raw_dst.is_null ());
    assert! (!raw_src.is_null ());

    let dst: &mut RsvgBbox = unsafe { &mut (*raw_dst) };
    let src: &RsvgBbox = unsafe { &*raw_src };

    if src.is_virgin () {
        return;
    }

    let (mut xmin, mut ymin, mut xmax, mut ymax) = if !dst.is_virgin () {
        ((dst.rect.x + dst.rect.width), (dst.rect.y + dst.rect.height), dst.rect.x, dst.rect.y)
    } else {
        (0.0, 0.0, 0.0, 0.0)
    };

    let mut affine = dst.affine;

    affine.invert ();
    affine = cairo::Matrix::multiply (&src.affine, &affine);

    /* This is a trick.  See rsvg_bbox_insert() for a description of how it works. */
    for i in 0..4 {
        let rx: f64 = src.rect.x + src.rect.width * f64::from(i % 2);
        let ry: f64 = src.rect.y + src.rect.height * f64::from(i / 2);
        let x = affine.xx * rx + affine.xy * ry + affine.x0;
        let y = affine.yx * rx + affine.yy * ry + affine.y0;

        if dst.is_virgin () {
            xmin = x;
            xmax = x;
            ymin = y;
            ymax = y;
            dst.virgin = false.to_glib ();
        } else {
            if x < xmin { xmin = x; }
            if x > xmax { xmax = x; }
            if y < ymin { ymin = y; }
            if y > ymax { ymax = y; }
        }
    }

    if xmin < dst.rect.x { xmin = dst.rect.x; }
    if ymin < dst.rect.y { ymin = dst.rect.y; }

    if xmax > dst.rect.x + dst.rect.width { xmax = dst.rect.x + dst.rect.width; }
    if ymax > dst.rect.y + dst.rect.height { ymax = dst.rect.y + dst.rect.height; }

    dst.rect.x = xmin;
    dst.rect.width = xmax - xmin;
    dst.rect.y = ymin;
    dst.rect.height = ymax - ymin;
}
<commit_msg>bbox.rs: Fix typo in clippification<commit_after>use ::cairo;
use ::glib_sys;

use glib::translate::*;
use cairo::MatrixTrait;

/* Keep this in sync with ../../rsvg-private.h:RsvgBbox */
#[repr(C)]
pub struct RsvgBbox {
    pub rect:   cairo::Rectangle,
    pub affine: cairo::Matrix,
    virgin:     glib_sys::gboolean
}

impl RsvgBbox {
    pub fn is_virgin (&self) -> bool {
        from_glib (self.virgin)
    }
}

#[no_mangle]
pub extern fn rsvg_bbox_init (raw_bbox: *mut RsvgBbox, raw_matrix: *const cairo::Matrix) {
    assert! (!raw_bbox.is_null ());
    assert! (!raw_matrix.is_null ());

    let bbox: &mut RsvgBbox = unsafe { &mut (*raw_bbox) };

    bbox.virgin = true.to_glib ();
    bbox.affine = unsafe { *raw_matrix };
}

#[no_mangle]
pub extern fn rsvg_bbox_insert (raw_dst: *mut RsvgBbox, raw_src: *const RsvgBbox) {
    assert! (!raw_dst.is_null ());
    assert! (!raw_src.is_null ());

    let dst: &mut RsvgBbox = unsafe { &mut (*raw_dst) };
    let src: &RsvgBbox = unsafe { &*raw_src };

    if src.is_virgin () {
        return;
    }

    let (mut xmin, mut ymin, mut xmax, mut ymax) = if !dst.is_virgin () {
        (dst.rect.x,
         dst.rect.y,
         (dst.rect.x + dst.rect.width),
         (dst.rect.y + dst.rect.height))
    } else {
        (0.0, 0.0, 0.0, 0.0)
    };

    let mut affine = dst.affine;

    affine.invert (); // this will panic!() if it's not invertible... should we check on our own?
    affine = cairo::Matrix::multiply (&src.affine, &affine);

    /* This is a trick.  We want to transform each of the corners of
     * the rectangle defined by src.rect with the affine
     * transformation, and get the bounding box of all the four
     * resulting points.  The modulus and division accomplish this by
     * running through all the combinations of adding or not adding
     * the width/height to the first point src.rect.(x, y).
     */
    for i in 0..4 {
        let rx: f64 = src.rect.x + src.rect.width * f64::from(i % 2);
        let ry: f64 = src.rect.y + src.rect.height * f64::from(i / 2);
        let x: f64  = affine.xx * rx + affine.xy * ry + affine.x0;
        let y: f64  = affine.yx * rx + affine.yy * ry + affine.y0;

        if dst.is_virgin () {
            xmin = x;
            xmax = x;
            ymin = y;
            ymax = y;
            dst.virgin = false.to_glib ();
        } else {
            if x < xmin { xmin = x; }
            if x > xmax { xmax = x; }
            if y < ymin { ymin = y; }
            if y > ymax { ymax = y; }
        }
    }

    dst.rect.x = xmin;
    dst.rect.y = ymin;
    dst.rect.width = xmax - xmin;
    dst.rect.height = ymax - ymin;
}

#[no_mangle]
pub extern fn rsvg_bbox_clip (raw_dst: *mut RsvgBbox, raw_src: *const RsvgBbox) {
    assert! (!raw_dst.is_null ());
    assert! (!raw_src.is_null ());

    let dst: &mut RsvgBbox = unsafe { &mut (*raw_dst) };
    let src: &RsvgBbox = unsafe { &*raw_src };

    if src.is_virgin () {
        return;
    }

    let (mut xmin, mut ymin, mut xmax, mut ymax) = if !dst.is_virgin () {
        ((dst.rect.x + dst.rect.width),
         (dst.rect.y + dst.rect.height),
         dst.rect.x,
         dst.rect.y)
    } else {
        (0.0, 0.0, 0.0, 0.0)
    };

    let mut affine = dst.affine;

    affine.invert ();
    affine = cairo::Matrix::multiply (&src.affine, &affine);

    /* This is a trick.  See rsvg_bbox_insert() for a description of how it works. */
    for i in 0..4 {
        let rx: f64 = src.rect.x + src.rect.width * f64::from(i % 2);
        let ry: f64 = src.rect.y + src.rect.height * f64::from(i / 2);
        let x = affine.xx * rx + affine.xy * ry + affine.x0;
        let y = affine.yx * rx + affine.yy * ry + affine.y0;

        if dst.is_virgin () {
            xmin = x;
            xmax = x;
            ymin = y;
            ymax = y;
            dst.virgin = false.to_glib ();
        } else {
            if x < xmin { xmin = x; }
            if x > xmax { xmax = x; }
            if y < ymin { ymin = y; }
            if y > ymax { ymax = y; }
        }
    }

    if xmin < dst.rect.x { xmin = dst.rect.x; }
    if ymin < dst.rect.y { ymin = dst.rect.y; }

    if xmax > dst.rect.x + dst.rect.width { xmax = dst.rect.x + dst.rect.width; }
    if ymax > dst.rect.y + dst.rect.height { ymax = dst.rect.y + dst.rect.height; }

    dst.rect.x = xmin;
    dst.rect.width = xmax - xmin;
    dst.rect.y = ymin;
    dst.rect.height = ymax - ymin;
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use fnv::FnvHashSet;
use graphql_ir::Program;
use graphql_transforms::{
    flatten, generate_id_field, generate_typename, inline_fragments, remove_base_fragments,
    skip_client_extensions, sort_selections,
};
use interner::StringKey;

pub struct Programs<'schema> {
    pub reader: Program<'schema>,
    pub normalization: Program<'schema>,
    pub operation_text: Program<'schema>,
}

pub fn apply_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Programs<'schema> {
    // common
    //  |- reader
    //  |- query
    //     |- normalization
    //     |- operation_text
    let common_program = apply_common_transforms(&program);
    let reader_program = apply_reader_transforms(&common_program, base_fragment_names);
    let query_program = apply_operation_transforms(&common_program);
    let normalization_program = apply_normalization_transforms(&query_program);
    let operation_text_program = apply_operation_text_transforms(&query_program);

    Programs {
        reader: reader_program,
        normalization: normalization_program,
        operation_text: operation_text_program,
    }
}

/// Applies transforms that apply to every output.
fn apply_common_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - DisallowIdAsAlias
    // - ConnectionTransform
    // - RelayDirectiveTransform
    // - MaskTransform
    // - MatchTransform
    // - RefetchableFragmentTransform
    // - DeferStreamTransform

    // TODO remove this clone once some transform is applied
    program.clone()
}

/// Applies transforms only for generated reader code.
/// Corresponds to the "fragment transforms" in the JS compiler.
fn apply_reader_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Program<'schema> {
    // JS compiler
    // - ClientExtensionsTransform
    // - FieldHandleTransform
    // - InlineDataFragmentTransform
    // - FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform

    let program = remove_base_fragments(&program, base_fragment_names);
    let program = flatten(&program, true);

    sort_selections(&program)
}

/// Applies transforms that apply to all operation artifacts.
/// Corresponds to the "query transforms" in the JS compiler.
fn apply_operation_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - ValidateUnusedVariablesTransform
    // - ApplyFragmentArgumentTransform
    // - ValidateGlobalVariablesTransform
    // - GenerateIDFieldTransform
    // - TestOperationTransform

    generate_id_field(&program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the generated normalization code.
///
/// Corresponds to the "codegen transforms" in the JS compiler
fn apply_normalization_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - SkipUnreachableNodeTransform
    // - SplitModuleImportTransform
    // - InlineFragmentsTransform
    // - ClientExtensionsTransform
    // - FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform
    // - GenerateTypeNameTransform
    // - ValidateServerOnlyDirectivesTransform

    let program = inline_fragments(&program);
    let program = flatten(&program, true);
    let program = generate_typename(&program);
    sort_selections(&program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the printed operation text.
///
/// Corresponds to the "print transforms" in the JS compiler
fn apply_operation_text_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - ClientExtensionsTransform
    // - SkipClientExtensionsTransform
    // - SkipUnreachableNodeTransform
    // - FlattenTransform, flattenAbstractTypes: false
    // - GenerateTypeNameTransform
    // - SkipHandleFieldTransform
    // - FilterDirectivesTransform
    // - SkipUnusedVariablesTransform
    // - ValidateRequiredArgumentsTransform

    let program = skip_client_extensions(&program);
    let program = flatten(&program, false);
    let program = generate_typename(&program);
    sort_selections(&program)
}
<commit_msg>naming: query -> operation<commit_after>/*
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

use fnv::FnvHashSet;
use graphql_ir::Program;
use graphql_transforms::{
    flatten, generate_id_field, generate_typename, inline_fragments, remove_base_fragments,
    skip_client_extensions, sort_selections,
};
use interner::StringKey;

pub struct Programs<'schema> {
    pub reader: Program<'schema>,
    pub normalization: Program<'schema>,
    pub operation_text: Program<'schema>,
}

pub fn apply_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Programs<'schema> {
    // common
    //  |- reader
    //  |- operation
    //     |- normalization
    //     |- operation_text
    let common_program = apply_common_transforms(&program);
    let reader_program = apply_reader_transforms(&common_program, base_fragment_names);
    let operation_program = apply_operation_transforms(&common_program);
    let normalization_program = apply_normalization_transforms(&operation_program);
    let operation_text_program = apply_operation_text_transforms(&operation_program);

    Programs {
        reader: reader_program,
        normalization: normalization_program,
        operation_text: operation_text_program,
    }
}

/// Applies transforms that apply to every output.
fn apply_common_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - DisallowIdAsAlias
    // - ConnectionTransform
    // - RelayDirectiveTransform
    // - MaskTransform
    // - MatchTransform
    // - RefetchableFragmentTransform
    // - DeferStreamTransform

    // TODO remove this clone once some transform is applied
    program.clone()
}

/// Applies transforms only for generated reader code.
/// Corresponds to the "fragment transforms" in the JS compiler.
fn apply_reader_transforms<'schema>(
    program: &Program<'schema>,
    base_fragment_names: &FnvHashSet<StringKey>,
) -> Program<'schema> {
    // JS compiler
    // - ClientExtensionsTransform
    // - FieldHandleTransform
    // - InlineDataFragmentTransform
    // - FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform

    let program = remove_base_fragments(&program, base_fragment_names);
    let program = flatten(&program, true);

    sort_selections(&program)
}

/// Applies transforms that apply to all operation artifacts.
/// Corresponds to the "query transforms" in the JS compiler.
fn apply_operation_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - ValidateUnusedVariablesTransform
    // - ApplyFragmentArgumentTransform
    // - ValidateGlobalVariablesTransform
    // - GenerateIDFieldTransform
    // - TestOperationTransform

    generate_id_field(&program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the generated normalization code.
///
/// Corresponds to the "codegen transforms" in the JS compiler
fn apply_normalization_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - SkipUnreachableNodeTransform
    // - SplitModuleImportTransform
    // - InlineFragmentsTransform
    // - ClientExtensionsTransform
    // - FlattenTransform, flattenAbstractTypes: true
    // - SkipRedundantNodesTransform
    // - GenerateTypeNameTransform
    // - ValidateServerOnlyDirectivesTransform

    let program = inline_fragments(&program);
    let program = flatten(&program, true);
    let program = generate_typename(&program);
    sort_selections(&program)
}

/// After the operation transforms, this applies further transforms that only
/// apply to the printed operation text.
///
/// Corresponds to the "print transforms" in the JS compiler
fn apply_operation_text_transforms<'schema>(program: &Program<'schema>) -> Program<'schema> {
    // JS compiler
    // - ClientExtensionsTransform
    // - SkipClientExtensionsTransform
    // - SkipUnreachableNodeTransform
    // - FlattenTransform, flattenAbstractTypes: false
    // - GenerateTypeNameTransform
    // - SkipHandleFieldTransform
    // - FilterDirectivesTransform
    // - SkipUnusedVariablesTransform
    // - ValidateRequiredArgumentsTransform

    let program = skip_client_extensions(&program);
    let program = flatten(&program, false);
    let program = generate_typename(&program);
    sort_selections(&program)
}
<|endoftext|>


<commit_before>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [URL], the x-www-form-urlencoded format.
//! - [XML], the flexible machine-friendly W3C standard.
//!   *(deserialization only)*
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Redis], deserialize values from Redis when using [redis-rs].
//!   *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [XML]: https://github.com/RReverser/serde-xml-rs
//! [Envy]: https://github.com/softprops/envy
//! [Redis]: https://github.com/OneSignal/serde-redis
//! [Cargo]: http://doc.crates.io/manifest.html
//! [redis-rs]: https://crates.io/crates/redis

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.80")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cast_lossless,
        const_static_lifetime,
        doc_markdown,
        linkedlist,
        needless_pass_by_value,
        redundant_field_names,
        type_complexity,
        unreadable_literal,
        zero_prefixed_literal
    )
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
    cast_possible_truncation,
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
// simplifies some macros
    invalid_upcast_comparisons,
// things are often more readable this way
    decimal_literal_representation,
    option_unwrap_used,
    result_unwrap_used,
    shadow_reuse,
    single_match_else,
    stutter,
    use_self,
// not practical
    indexing_slicing,
    many_single_char_names,
    missing_docs_in_private_items,
    similar_names,
// alternative is not stable
    empty_enum,
    use_debug,
))]
// Blacklisted Rust lints.
//
// Compiler bug involving unused_imports:
// https://github.com/rust-lang/rust/issues/51661
#![deny(missing_docs, /*unused_imports*/)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::String;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;

    #[cfg(range_inclusive)]
    pub use self::core::ops::RangeInclusive;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
//     [features]
//     serde-impls = ["serde", "serde_derive"]
//
//     [dependencies]
//     serde = { version = "1.0", optional = true }
//     serde_derive = { version = "1.0", optional = true }
//
//     # Used like this:
//     # #[cfg(feature = "serde-impls")]
//     # #[macro_use]
//     # extern crate serde_derive;
//     #
//     # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
//     [dependencies]
//     serde = { version = "1.0", optional = true, features = ["derive"] }
//
//     # Used like this:
//     # #[cfg(feature = "serde")]
//     # #[macro_use]
//     # extern crate serde;
//     #
//     # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<commit_msg>Sync links from serde.rs website<commit_after>//! # Serde
//!
//! Serde is a framework for ***ser***ializing and ***de***serializing Rust data
//! structures efficiently and generically.
//!
//! The Serde ecosystem consists of data structures that know how to serialize
//! and deserialize themselves along with data formats that know how to
//! serialize and deserialize other things. Serde provides the layer by which
//! these two groups interact with each other, allowing any supported data
//! structure to be serialized and deserialized using any supported data format.
//!
//! See the Serde website [https://serde.rs/] for additional documentation and
//! usage examples.
//!
//! [https://serde.rs/]: https://serde.rs/
//!
//! ## Design
//!
//! Where many other languages rely on runtime reflection for serializing data,
//! Serde is instead built on Rust's powerful trait system. A data structure
//! that knows how to serialize and deserialize itself is one that implements
//! Serde's `Serialize` and `Deserialize` traits (or uses Serde's derive
//! attribute to automatically generate implementations at compile time). This
//! avoids any overhead of reflection or runtime type information. In fact in
//! many situations the interaction between data structure and data format can
//! be completely optimized away by the Rust compiler, leaving Serde
//! serialization to perform the same speed as a handwritten serializer for the
//! specific selection of data structure and data format.
//!
//! ## Data formats
//!
//! The following is a partial list of data formats that have been implemented
//! for Serde by the community.
//!
//! - [JSON], the ubiquitous JavaScript Object Notation used by many HTTP APIs.
//! - [Bincode], a compact binary format
//!   used for IPC within the Servo rendering engine.
//! - [CBOR], a Concise Binary Object Representation designed for small message
//!   size without the need for version negotiation.
//! - [YAML], a popular human-friendly configuration language that ain't markup
//!   language.
//! - [MessagePack], an efficient binary format that resembles a compact JSON.
//! - [TOML], a minimal configuration format used by [Cargo].
//! - [Pickle], a format common in the Python world.
//! - [RON], a Rusty Object Notation.
//! - [BSON], the data storage and network transfer format used by MongoDB.
//! - [Avro], a binary format used within Apache Hadoop, with support for schema
//!   definition.
//! - [Hjson], a variant of JSON designed to be readable and writable by humans.
//! - [JSON5], A superset of JSON including some productions from ES5.
//! - [URL], the x-www-form-urlencoded format.
//! - [Envy], a way to deserialize environment variables into Rust structs.
//!   *(deserialization only)*
//! - [Envy Store], a way to deserialize [AWS Parameter Store] parameters into
//!   Rust structs. *(deserialization only)*
//!
//! [JSON]: https://github.com/serde-rs/json
//! [Bincode]: https://github.com/TyOverby/bincode
//! [CBOR]: https://github.com/pyfisch/cbor
//! [YAML]: https://github.com/dtolnay/serde-yaml
//! [MessagePack]: https://github.com/3Hren/msgpack-rust
//! [TOML]: https://github.com/alexcrichton/toml-rs
//! [Pickle]: https://github.com/birkenfeld/serde-pickle
//! [RON]: https://github.com/ron-rs/ron
//! [BSON]: https://github.com/zonyitoo/bson-rs
//! [Avro]: https://github.com/flavray/avro-rs
//! [Hjson]: https://github.com/laktak/hjson-rust
//! [JSON5]: https://github.com/callum-oakley/json5-rs
//! [URL]: https://github.com/nox/serde_urlencoded
//! [Envy]: https://github.com/softprops/envy
//! [Envy Store]: https://github.com/softprops/envy-store
//! [Cargo]: http://doc.crates.io/manifest.html
//! [AWS Parameter Store]: https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-paramstore.html

////////////////////////////////////////////////////////////////////////////////

// Serde types in rustdoc of other crates get linked to here.
#![doc(html_root_url = "https://docs.rs/serde/1.0.80")]
// Support using Serde without the standard library!
#![cfg_attr(not(feature = "std"), no_std)]
// Unstable functionality only if the user asks for it. For tracking and
// discussion of these features please refer to this issue:
//
//    https://github.com/serde-rs/serde/issues/812
#![cfg_attr(feature = "unstable", feature(specialization, never_type))]
#![cfg_attr(feature = "alloc", feature(alloc))]
#![cfg_attr(feature = "cargo-clippy", allow(renamed_and_removed_lints))]
#![cfg_attr(feature = "cargo-clippy", deny(clippy, clippy_pedantic))]
// Whitelisted clippy lints
#![cfg_attr(
    feature = "cargo-clippy",
    allow(
        cast_lossless,
        const_static_lifetime,
        doc_markdown,
        linkedlist,
        needless_pass_by_value,
        redundant_field_names,
        type_complexity,
        unreadable_literal,
        zero_prefixed_literal
    )
)]
// Whitelisted clippy_pedantic lints
#![cfg_attr(feature = "cargo-clippy", allow(
// integer and float ser/de requires these sorts of casts
    cast_possible_truncation,
    cast_possible_wrap,
    cast_precision_loss,
    cast_sign_loss,
// simplifies some macros
    invalid_upcast_comparisons,
// things are often more readable this way
    decimal_literal_representation,
    option_unwrap_used,
    result_unwrap_used,
    shadow_reuse,
    single_match_else,
    stutter,
    use_self,
// not practical
    indexing_slicing,
    many_single_char_names,
    missing_docs_in_private_items,
    similar_names,
// alternative is not stable
    empty_enum,
    use_debug,
))]
// Blacklisted Rust lints.
//
// Compiler bug involving unused_imports:
// https://github.com/rust-lang/rust/issues/51661
#![deny(missing_docs, /*unused_imports*/)]

////////////////////////////////////////////////////////////////////////////////

#[cfg(feature = "alloc")]
extern crate alloc;

/// A facade around all the types we need from the `std`, `core`, and `alloc`
/// crates. This avoids elaborate import wrangling having to happen in every
/// module.
mod lib {
    mod core {
        #[cfg(not(feature = "std"))]
        pub use core::*;
        #[cfg(feature = "std")]
        pub use std::*;
    }

    pub use self::core::{cmp, iter, mem, num, slice, str};
    pub use self::core::{f32, f64};
    pub use self::core::{i16, i32, i64, i8, isize};
    pub use self::core::{u16, u32, u64, u8, usize};

    pub use self::core::cell::{Cell, RefCell};
    pub use self::core::clone::{self, Clone};
    pub use self::core::convert::{self, From, Into};
    pub use self::core::default::{self, Default};
    pub use self::core::fmt::{self, Debug, Display};
    pub use self::core::marker::{self, PhantomData};
    pub use self::core::ops::Range;
    pub use self::core::option::{self, Option};
    pub use self::core::result::{self, Result};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::borrow::{Cow, ToOwned};
    #[cfg(feature = "std")]
    pub use std::borrow::{Cow, ToOwned};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::string::{String, ToString};
    #[cfg(feature = "std")]
    pub use std::string::String;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::vec::Vec;
    #[cfg(feature = "std")]
    pub use std::vec::Vec;

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::boxed::Box;
    #[cfg(feature = "std")]
    pub use std::boxed::Box;

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::rc::{Rc, Weak as RcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::rc::{Rc, Weak as RcWeak};

    #[cfg(all(feature = "rc", feature = "alloc", not(feature = "std")))]
    pub use alloc::sync::{Arc, Weak as ArcWeak};
    #[cfg(all(feature = "rc", feature = "std"))]
    pub use std::sync::{Arc, Weak as ArcWeak};

    #[cfg(all(feature = "alloc", not(feature = "std")))]
    pub use alloc::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};
    #[cfg(feature = "std")]
    pub use std::collections::{BTreeMap, BTreeSet, BinaryHeap, LinkedList, VecDeque};

    #[cfg(feature = "std")]
    pub use std::{error, net};

    #[cfg(feature = "std")]
    pub use std::collections::{HashMap, HashSet};
    #[cfg(feature = "std")]
    pub use std::ffi::{CStr, CString, OsStr, OsString};
    #[cfg(feature = "std")]
    pub use std::hash::{BuildHasher, Hash};
    #[cfg(feature = "std")]
    pub use std::io::Write;
    #[cfg(feature = "std")]
    pub use std::num::Wrapping;
    #[cfg(feature = "std")]
    pub use std::path::{Path, PathBuf};
    #[cfg(feature = "std")]
    pub use std::sync::{Mutex, RwLock};
    #[cfg(feature = "std")]
    pub use std::time::{SystemTime, UNIX_EPOCH};

    #[cfg(any(core_duration, feature = "std"))]
    pub use self::core::time::Duration;

    #[cfg(range_inclusive)]
    pub use self::core::ops::RangeInclusive;
}

////////////////////////////////////////////////////////////////////////////////

#[macro_use]
mod macros;

#[macro_use]
mod integer128;

pub mod de;
pub mod ser;

#[doc(inline)]
pub use de::{Deserialize, Deserializer};
#[doc(inline)]
pub use ser::{Serialize, Serializer};

// Generated code uses these to support no_std. Not public API.
#[doc(hidden)]
pub mod export;

// Helpers used by generated code and doc tests. Not public API.
#[doc(hidden)]
pub mod private;

// Re-export #[derive(Serialize, Deserialize)].
//
// This is a workaround for https://github.com/rust-lang/cargo/issues/1286.
// Without this re-export, crates that put Serde derives behind a cfg_attr would
// need to use some silly feature name that depends on both serde and
// serde_derive.
//
//     [features]
//     serde-impls = ["serde", "serde_derive"]
//
//     [dependencies]
//     serde = { version = "1.0", optional = true }
//     serde_derive = { version = "1.0", optional = true }
//
//     # Used like this:
//     # #[cfg(feature = "serde-impls")]
//     # #[macro_use]
//     # extern crate serde_derive;
//     #
//     # #[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The re-exported derives allow crates to use "serde" as the name of their
// Serde feature which is more intuitive.
//
//     [dependencies]
//     serde = { version = "1.0", optional = true, features = ["derive"] }
//
//     # Used like this:
//     # #[cfg(feature = "serde")]
//     # #[macro_use]
//     # extern crate serde;
//     #
//     # #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
//     # struct S { /* ... */ }
//
// The reason re-exporting is not enabled by default is that disabling it would
// be annoying for crates that provide handwritten impls or data formats. They
// would need to disable default features and then explicitly re-enable std.
#[cfg(feature = "serde_derive")]
#[allow(unused_imports)]
#[macro_use]
extern crate serde_derive;
#[cfg(feature = "serde_derive")]
#[doc(hidden)]
pub use serde_derive::*;
<|endoftext|>