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

use collada;
use gfx;
use gfx::traits::*;
use gfx_texture;

use math::*;
use skeleton::Skeleton;

const MAX_JOINTS: usize = 64;

pub struct SkinnedRenderBatch<R: gfx::Resources> {
    skinning_transforms_buffer: gfx::BufferHandle<R, [[f32; 4]; 4]>,
    batch: gfx::batch::RefBatch<SkinnedShaderParams<R>>,
}

pub struct SkinnedRenderer<R: gfx::Resources> {
    skeleton: Skeleton, // TODO Should this be a ref? Should this just be the joints?
    render_batches: Vec<SkinnedRenderBatch<R>>,
    context: gfx::render::batch::Context<R>,
}

impl<R: gfx::Resources> SkinnedRenderer<R> {

    pub fn from_collada<
        F: gfx::Factory<R>,
    > (
        factory: &mut F,
        collada_document: collada::document::ColladaDocument,
        texture_paths: Vec<&str>, // TODO - read from the COLLADA document (if available)
    ) -> Result<SkinnedRenderer<R>, gfx::ProgramError> {

        let program = match factory.link_program(SKINNED_VERTEX_SHADER.clone(), SKINNED_FRAGMENT_SHADER.clone()) {
            Ok(program_handle) => program_handle,
            Err(e) => return Err(e),
        };

        let obj_set = collada_document.get_obj_set().unwrap();

        let mut skeleton_set = collada_document.get_skeletons().unwrap();
        let mut animations = collada_document.get_animations();
        let skeleton = Skeleton::from_collada(&skeleton_set[0]);

        let mut render_batches = Vec::new();

        let mut context = gfx::render::batch::Context::new();

        for (i, object) in obj_set.objects.iter().enumerate().take(6) {

            let mut vertex_data: Vec<SkinnedVertex> = Vec::new();
            let mut index_data: Vec<u32> = Vec::new();

            get_vertex_index_data(&object, &mut vertex_data, &mut index_data);

            let mesh = factory.create_mesh(vertex_data.as_slice());

            let state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

            let slice = factory
                .create_buffer_index::<u32>(index_data.as_slice())
                .to_slice(gfx::PrimitiveType::TriangleList);

            let skinning_transforms_buffer = factory.create_buffer::<[[f32; 4]; 4]>(MAX_JOINTS, gfx::BufferUsage::Dynamic);

            let texture = gfx_texture::Texture::from_path(
                factory,
                &Path::new(&texture_paths[i]),
                &gfx_texture::Settings::new()
            ).unwrap();

            let sampler = factory.create_sampler(
                gfx::tex::SamplerInfo::new(
                    gfx::tex::FilterMethod::Trilinear,
                    gfx::tex::WrapMode::Clamp
                )
            );

            let shader_params = SkinnedShaderParams {
                u_model_view_proj: mat4_id(),
                u_model_view: mat4_id(),
                u_skinning_transforms: skinning_transforms_buffer.raw().clone(),
                u_texture: (texture.handle, Some(sampler)),
            };

            let batch: gfx::batch::RefBatch<SkinnedShaderParams<R>> = context.make_batch(&program, shader_params, &mesh, slice, &state).unwrap();

            render_batches.push(SkinnedRenderBatch {
                batch: batch,
                skinning_transforms_buffer: skinning_transforms_buffer,
            });
        }

        Ok(SkinnedRenderer {
            render_batches: render_batches,
            skeleton: skeleton.clone(),
            context: context,
        })
    }

    pub fn render_canvas<
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>,
        O: gfx::render::target::Output<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    >(
        &mut self,
        canvas: &mut gfx::Canvas<O, D, F>,
        view: [[f32; 4]; 4],
        projection: [[f32; 4]; 4],
        joint_poses: &[Matrix4<f32>]
    ) {
        self.render(&mut canvas.renderer, &mut canvas.factory, &canvas.output, view, projection, joint_poses);
    }

    pub fn render<
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>,
        O: gfx::render::target::Output<R>,
    >(
        &mut self,
        renderer: &mut gfx::Renderer<R, C>,
        factory: &mut F,
        output: &O,
        view: [[f32; 4]; 4],
        projection: [[f32; 4]; 4],
        joint_poses: &[Matrix4<f32>]
    ) {

        let skinning_transforms = self.calculate_skinning_transforms(&joint_poses);

        for material in self.render_batches.iter_mut() {
            material.batch.params.u_model_view = view;
            material.batch.params.u_model_view_proj = projection;

            // FIXME -- should all be able to share the same buffer
            factory.update_buffer(&material.skinning_transforms_buffer, &skinning_transforms[..], 0);

            renderer.draw(&(&material.batch, &self.context), output).unwrap();
        }
    }

    ///
    /// TODO - don't allocate a new vector
    ///
    pub fn calculate_skinning_transforms(&self, global_poses: &[Matrix4<f32>]) -> Vec<Matrix4<f32>> {

        use std::f32::consts::PI;
        use std::num::{Float};

        self.skeleton.joints.iter().enumerate().map(|(i, joint)| {
            row_mat4_mul(global_poses[i], joint.inverse_bind_pose)
        }).collect()
    }
}

#[shader_param]
struct SkinnedShaderParams<R: gfx::Resources> {
    u_model_view_proj: [[f32; 4]; 4],
    u_model_view: [[f32; 4]; 4],
    u_skinning_transforms: gfx::RawBufferHandle<R>,
    u_texture: gfx::shade::TextureParam<R>,
}

#[vertex_format]
#[derive(Copy)]
#[derive(Clone)]
#[derive(Debug)]
struct SkinnedVertex {
    pos: [f32; 3],
    normal: [f32; 3],
    uv: [f32; 2],
    joint_indices: [i32; 4],
    joint_weights: [f32; 4], // TODO last weight is redundant
}

impl Default for SkinnedVertex {
    fn default() -> SkinnedVertex {
        SkinnedVertex {
            pos: [0.0; 3],
            normal: [0.0; 3],
            uv: [0.0; 2],
            joint_indices: [0; 4],
            joint_weights: [0.0; 4],
        }
    }
}

static SKINNED_VERTEX_SHADER: &'static [u8] = b"
    #version 150 core

    uniform mat4 u_model_view_proj;
    uniform mat4 u_model_view;

    const int MAX_JOINTS = 64;

    uniform u_skinning_transforms {
        mat4 skinning_transforms[MAX_JOINTS];
    };

    in vec3 pos, normal;
    in vec2 uv;

    in ivec4 joint_indices;
    in vec4 joint_weights;

    out vec3 v_normal;
    out vec2 v_TexCoord;

    void main() {
        v_TexCoord = vec2(uv.x, 1 - uv.y); // this feels like a bug with gfx?

        vec4 adjustedVertex;
        vec4 adjustedNormal;

        vec4 bindPoseVertex = vec4(pos, 1.0);
        vec4 bindPoseNormal = vec4(normal, 0.0);

        adjustedVertex = bindPoseVertex * skinning_transforms[joint_indices.x] * joint_weights.x;
        adjustedNormal = bindPoseNormal * skinning_transforms[joint_indices.x] * joint_weights.x;

        adjustedVertex = adjustedVertex + bindPoseVertex * skinning_transforms[joint_indices.y] * joint_weights.y;
        adjustedNormal = adjustedNormal + bindPoseNormal * skinning_transforms[joint_indices.y] * joint_weights.y;

        adjustedVertex = adjustedVertex + bindPoseVertex * skinning_transforms[joint_indices.z] * joint_weights.z;
        adjustedNormal = adjustedNormal + bindPoseNormal * skinning_transforms[joint_indices.z] * joint_weights.z;

        // TODO just use remainder for this weight?
        adjustedVertex = adjustedVertex + bindPoseVertex * skinning_transforms[joint_indices.a] * joint_weights.a;
        adjustedNormal = adjustedNormal + bindPoseNormal * skinning_transforms[joint_indices.a] * joint_weights.a;

        gl_Position = u_model_view_proj * adjustedVertex;
        v_normal = normalize(u_model_view * adjustedNormal).xyz;
    }
";

static SKINNED_FRAGMENT_SHADER: &'static [u8] = b"
    #version 150

    uniform sampler2D u_texture;

    in vec3 v_normal;
    out vec4 out_color;

    in vec2 v_TexCoord;

    void main() {
        vec4 texColor = texture(u_texture, v_TexCoord);

        // unidirectional light in direction as camera
        vec3 light = vec3(0.0, 0.0, 1.0);
        light = normalize(light);
        float intensity = max(dot(v_normal, light), 0.0);

        out_color = vec4(intensity, intensity, intensity, 1.0) * texColor;
    }
";

fn vtn_to_vertex(a: collada::VTNIndex, obj: &collada::Object) -> SkinnedVertex
{
    let mut vertex: SkinnedVertex = Default::default();
    let position = obj.vertices[a.0];

    vertex.pos = [position.x as f32, position.y as f32, position.z as f32];

    if obj.joint_weights.len() == obj.vertices.len() {
        let weights = obj.joint_weights[a.0];
        vertex.joint_weights = weights.weights;
        vertex.joint_indices = [
            weights.joints[0] as i32,
            weights.joints[1] as i32,
            weights.joints[2] as i32,
            weights.joints[3] as i32,
        ];
    }

    if let Some(uv) = a.1 {
        let uv = obj.tex_vertices[uv];
        vertex.uv = [uv.x as f32, uv.y as f32];
    }

    if let Some(normal) = a.2 {
        let normal = obj.normals[normal];
        vertex.normal = [normal.x as f32, normal.y as f32, normal.z as f32];
    }

    vertex
}

fn get_vertex_index_data(obj: &collada::Object, vertex_data: &mut Vec<SkinnedVertex>, index_data: &mut Vec<u32>) {
    for geom in obj.geometry.iter() {
        let start = index_data.len();
        let mut i = vertex_data.len() as u32;
        let mut uvs: u32 = 0;
        let mut normals: u32 = 0;
        {
            let mut add = |a: collada::VTNIndex| {
                if let Some(_) = a.1 { uvs += 1; }
                if let Some(_) = a.2 { normals += 1; }
                vertex_data.push(vtn_to_vertex(a, obj));
                index_data.push(i);
                i += 1;
            };
            for shape in geom.shapes.iter() {
                match shape {
                    &collada::Shape::Triangle(a, b, c) => {
                        add(a);
                        add(b);
                        add(c);
                    }
                    _ => {}
                }
            }
        }
    }
}
<commit_msg>Update to latest gfx_texture<commit_after>use std::default::Default;
use std::path::Path;

use collada;
use gfx;
use gfx::traits::*;
use gfx_texture;

use math::*;
use skeleton::Skeleton;

const MAX_JOINTS: usize = 64;

pub struct SkinnedRenderBatch<R: gfx::Resources> {
    skinning_transforms_buffer: gfx::BufferHandle<R, [[f32; 4]; 4]>,
    batch: gfx::batch::RefBatch<SkinnedShaderParams<R>>,
}

pub struct SkinnedRenderer<R: gfx::Resources> {
    skeleton: Skeleton, // TODO Should this be a ref? Should this just be the joints?
    render_batches: Vec<SkinnedRenderBatch<R>>,
    context: gfx::render::batch::Context<R>,
}

impl<R: gfx::Resources> SkinnedRenderer<R> {

    pub fn from_collada<
        F: gfx::Factory<R>,
    > (
        factory: &mut F,
        collada_document: collada::document::ColladaDocument,
        texture_paths: Vec<&str>, // TODO - read from the COLLADA document (if available)
    ) -> Result<SkinnedRenderer<R>, gfx::ProgramError> {

        let program = match factory.link_program(SKINNED_VERTEX_SHADER.clone(), SKINNED_FRAGMENT_SHADER.clone()) {
            Ok(program_handle) => program_handle,
            Err(e) => return Err(e),
        };

        let obj_set = collada_document.get_obj_set().unwrap();

        let mut skeleton_set = collada_document.get_skeletons().unwrap();
        let mut animations = collada_document.get_animations();
        let skeleton = Skeleton::from_collada(&skeleton_set[0]);

        let mut render_batches = Vec::new();

        let mut context = gfx::render::batch::Context::new();

        for (i, object) in obj_set.objects.iter().enumerate().take(6) {

            let mut vertex_data: Vec<SkinnedVertex> = Vec::new();
            let mut index_data: Vec<u32> = Vec::new();

            get_vertex_index_data(&object, &mut vertex_data, &mut index_data);

            let mesh = factory.create_mesh(vertex_data.as_slice());

            let state = gfx::DrawState::new().depth(gfx::state::Comparison::LessEqual, true);

            let slice = factory
                .create_buffer_index::<u32>(index_data.as_slice())
                .to_slice(gfx::PrimitiveType::TriangleList);

            let skinning_transforms_buffer = factory.create_buffer::<[[f32; 4]; 4]>(MAX_JOINTS, gfx::BufferUsage::Dynamic);

            let texture = gfx_texture::Texture::from_path(
                factory,
                &Path::new(&texture_paths[i]),
                &gfx_texture::Settings::new()
            ).unwrap();

            let sampler = factory.create_sampler(
                gfx::tex::SamplerInfo::new(
                    gfx::tex::FilterMethod::Trilinear,
                    gfx::tex::WrapMode::Clamp
                )
            );

            let shader_params = SkinnedShaderParams {
                u_model_view_proj: mat4_id(),
                u_model_view: mat4_id(),
                u_skinning_transforms: skinning_transforms_buffer.raw().clone(),
                u_texture: (texture.handle(), Some(sampler)),
            };

            let batch: gfx::batch::RefBatch<SkinnedShaderParams<R>> = context.make_batch(&program, shader_params, &mesh, slice, &state).unwrap();

            render_batches.push(SkinnedRenderBatch {
                batch: batch,
                skinning_transforms_buffer: skinning_transforms_buffer,
            });
        }

        Ok(SkinnedRenderer {
            render_batches: render_batches,
            skeleton: skeleton.clone(),
            context: context,
        })
    }

    pub fn render_canvas<
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>,
        O: gfx::render::target::Output<R>,
        D: Device<Resources = R, CommandBuffer = C>,
    >(
        &mut self,
        canvas: &mut gfx::Canvas<O, D, F>,
        view: [[f32; 4]; 4],
        projection: [[f32; 4]; 4],
        joint_poses: &[Matrix4<f32>]
    ) {
        self.render(&mut canvas.renderer, &mut canvas.factory, &canvas.output, view, projection, joint_poses);
    }

    pub fn render<
        C: gfx::CommandBuffer<R>,
        F: gfx::Factory<R>,
        O: gfx::render::target::Output<R>,
    >(
        &mut self,
        renderer: &mut gfx::Renderer<R, C>,
        factory: &mut F,
        output: &O,
        view: [[f32; 4]; 4],
        projection: [[f32; 4]; 4],
        joint_poses: &[Matrix4<f32>]
    ) {

        let skinning_transforms = self.calculate_skinning_transforms(&joint_poses);

        for material in self.render_batches.iter_mut() {
            material.batch.params.u_model_view = view;
            material.batch.params.u_model_view_proj = projection;

            // FIXME -- should all be able to share the same buffer
            factory.update_buffer(&material.skinning_transforms_buffer, &skinning_transforms[..], 0);

            renderer.draw(&(&material.batch, &self.context), output).unwrap();
        }
    }

    ///
    /// TODO - don't allocate a new vector
    ///
    pub fn calculate_skinning_transforms(&self, global_poses: &[Matrix4<f32>]) -> Vec<Matrix4<f32>> {

        use std::f32::consts::PI;
        use std::num::{Float};

        self.skeleton.joints.iter().enumerate().map(|(i, joint)| {
            row_mat4_mul(global_poses[i], joint.inverse_bind_pose)
        }).collect()
    }
}

#[shader_param]
struct SkinnedShaderParams<R: gfx::Resources> {
    u_model_view_proj: [[f32; 4]; 4],
    u_model_view: [[f32; 4]; 4],
    u_skinning_transforms: gfx::RawBufferHandle<R>,
    u_texture: gfx::shade::TextureParam<R>,
}

#[vertex_format]
#[derive(Copy)]
#[derive(Clone)]
#[derive(Debug)]
struct SkinnedVertex {
    pos: [f32; 3],
    normal: [f32; 3],
    uv: [f32; 2],
    joint_indices: [i32; 4],
    joint_weights: [f32; 4], // TODO last weight is redundant
}

impl Default for SkinnedVertex {
    fn default() -> SkinnedVertex {
        SkinnedVertex {
            pos: [0.0; 3],
            normal: [0.0; 3],
            uv: [0.0; 2],
            joint_indices: [0; 4],
            joint_weights: [0.0; 4],
        }
    }
}

static SKINNED_VERTEX_SHADER: &'static [u8] = b"
    #version 150 core

    uniform mat4 u_model_view_proj;
    uniform mat4 u_model_view;

    const int MAX_JOINTS = 64;

    uniform u_skinning_transforms {
        mat4 skinning_transforms[MAX_JOINTS];
    };

    in vec3 pos, normal;
    in vec2 uv;

    in ivec4 joint_indices;
    in vec4 joint_weights;

    out vec3 v_normal;
    out vec2 v_TexCoord;

    void main() {
        v_TexCoord = vec2(uv.x, 1 - uv.y); // this feels like a bug with gfx?

        vec4 adjustedVertex;
        vec4 adjustedNormal;

        vec4 bindPoseVertex = vec4(pos, 1.0);
        vec4 bindPoseNormal = vec4(normal, 0.0);

        adjustedVertex = bindPoseVertex * skinning_transforms[joint_indices.x] * joint_weights.x;
        adjustedNormal = bindPoseNormal * skinning_transforms[joint_indices.x] * joint_weights.x;

        adjustedVertex = adjustedVertex + bindPoseVertex * skinning_transforms[joint_indices.y] * joint_weights.y;
        adjustedNormal = adjustedNormal + bindPoseNormal * skinning_transforms[joint_indices.y] * joint_weights.y;

        adjustedVertex = adjustedVertex + bindPoseVertex * skinning_transforms[joint_indices.z] * joint_weights.z;
        adjustedNormal = adjustedNormal + bindPoseNormal * skinning_transforms[joint_indices.z] * joint_weights.z;

        // TODO just use remainder for this weight?
        adjustedVertex = adjustedVertex + bindPoseVertex * skinning_transforms[joint_indices.a] * joint_weights.a;
        adjustedNormal = adjustedNormal + bindPoseNormal * skinning_transforms[joint_indices.a] * joint_weights.a;

        gl_Position = u_model_view_proj * adjustedVertex;
        v_normal = normalize(u_model_view * adjustedNormal).xyz;
    }
";

static SKINNED_FRAGMENT_SHADER: &'static [u8] = b"
    #version 150

    uniform sampler2D u_texture;

    in vec3 v_normal;
    out vec4 out_color;

    in vec2 v_TexCoord;

    void main() {
        vec4 texColor = texture(u_texture, v_TexCoord);

        // unidirectional light in direction as camera
        vec3 light = vec3(0.0, 0.0, 1.0);
        light = normalize(light);
        float intensity = max(dot(v_normal, light), 0.0);

        out_color = vec4(intensity, intensity, intensity, 1.0) * texColor;
    }
";

fn vtn_to_vertex(a: collada::VTNIndex, obj: &collada::Object) -> SkinnedVertex
{
    let mut vertex: SkinnedVertex = Default::default();
    let position = obj.vertices[a.0];

    vertex.pos = [position.x as f32, position.y as f32, position.z as f32];

    if obj.joint_weights.len() == obj.vertices.len() {
        let weights = obj.joint_weights[a.0];
        vertex.joint_weights = weights.weights;
        vertex.joint_indices = [
            weights.joints[0] as i32,
            weights.joints[1] as i32,
            weights.joints[2] as i32,
            weights.joints[3] as i32,
        ];
    }

    if let Some(uv) = a.1 {
        let uv = obj.tex_vertices[uv];
        vertex.uv = [uv.x as f32, uv.y as f32];
    }

    if let Some(normal) = a.2 {
        let normal = obj.normals[normal];
        vertex.normal = [normal.x as f32, normal.y as f32, normal.z as f32];
    }

    vertex
}

fn get_vertex_index_data(obj: &collada::Object, vertex_data: &mut Vec<SkinnedVertex>, index_data: &mut Vec<u32>) {
    for geom in obj.geometry.iter() {
        let start = index_data.len();
        let mut i = vertex_data.len() as u32;
        let mut uvs: u32 = 0;
        let mut normals: u32 = 0;
        {
            let mut add = |a: collada::VTNIndex| {
                if let Some(_) = a.1 { uvs += 1; }
                if let Some(_) = a.2 { normals += 1; }
                vertex_data.push(vtn_to_vertex(a, obj));
                index_data.push(i);
                i += 1;
            };
            for shape in geom.shapes.iter() {
                match shape {
                    &collada::Shape::Triangle(a, b, c) => {
                        add(a);
                        add(b);
                        add(c);
                    }
                    _ => {}
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use super::entry::{Entry, EntryId, Timestamp};

#[derive(Debug)]
pub struct Storage<T: Send + 'static> {
    entries: BTreeMap<EntryId, Entry<T>>,
}

impl<T: Send + 'static> Storage<T> {
    pub fn new() -> Self {
        Storage { entries: BTreeMap::new() }
    }

    pub fn add_entry(&mut self, entry: Entry<T>) {
        self.entries.insert(entry.id(), entry);
    }

    pub fn has_entry(&self, entry: &Entry<T>) -> bool {
        self.entries.contains_key(&entry.id())
    }

    pub fn remove_entry(&mut self, id: EntryId) -> Option<Entry<T>> {
        self.entries.remove(&id)
    }

    // TODO: add max expired entries per turn (-> use environment variable)
    pub fn expire_entries(&mut self) -> Vec<Entry<T>> {
        let mut entries = Vec::<Entry<T>>::new();
        let now = Timestamp::now();
        let mut expired = Vec::<EntryId>::new();

        // This is the best solution I came up with
        // but it still bugs me that we have to iterate twice
        for id in self.entries.keys() {
            if id.timestamp() > now {
                break;
            }

            expired.push(*id);
        }

        for id in expired {
            // We can safely unwrap here because we know that
            // the item we're trying to remove actually exists
            entries.push(self.remove_entry(id).unwrap());
        }

        return entries;
    }
}<commit_msg>Return the idiomatic way<commit_after>use std::collections::BTreeMap;
use super::entry::{Entry, EntryId, Timestamp};

#[derive(Debug)]
pub struct Storage<T: Send + 'static> {
    entries: BTreeMap<EntryId, Entry<T>>,
}

impl<T: Send + 'static> Storage<T> {
    pub fn new() -> Self {
        Storage { entries: BTreeMap::new() }
    }

    pub fn add_entry(&mut self, entry: Entry<T>) {
        self.entries.insert(entry.id(), entry);
    }

    pub fn has_entry(&self, entry: &Entry<T>) -> bool {
        self.entries.contains_key(&entry.id())
    }

    pub fn remove_entry(&mut self, id: EntryId) -> Option<Entry<T>> {
        self.entries.remove(&id)
    }

    // TODO: add max expired entries per turn (-> use environment variable)
    pub fn expire_entries(&mut self) -> Vec<Entry<T>> {
        let mut entries = Vec::<Entry<T>>::new();
        let now = Timestamp::now();
        let mut expired = Vec::<EntryId>::new();

        // This is the best solution I came up with
        // but it still bugs me that we have to iterate twice
        for id in self.entries.keys() {
            if id.timestamp() > now {
                break;
            }

            expired.push(*id);
        }

        for id in expired {
            // We can safely unwrap here because we know that
            // the item we're trying to remove actually exists
            entries.push(self.remove_entry(id).unwrap());
        }

        entries
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::account_config::constants::{
    coin_struct_name, from_currency_code_string, CORE_CODE_ADDRESS,
};
use move_core_types::language_storage::{StructTag, TypeTag};

pub const COIN1_NAME: &str = "Coin1";
pub const COIN2_NAME: &str = "Coin2";

pub fn coin1_tag() -> TypeTag {
    TypeTag::Struct(StructTag {
        address: CORE_CODE_ADDRESS,
        module: from_currency_code_string(COIN1_NAME).unwrap(),
        name: coin_struct_name().to_owned(),
        type_params: vec![],
    })
}

pub fn coin2_tag() -> TypeTag {
    TypeTag::Struct(StructTag {
        address: CORE_CODE_ADDRESS,
        module: from_currency_code_string(COIN2_NAME).unwrap(),
        name: coin_struct_name().to_owned(),
        type_params: vec![],
    })
}
<commit_msg>Removing coin2_tag from types/src/account_config/constants/coins.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use crate::account_config::constants::{
    coin_struct_name, from_currency_code_string, CORE_CODE_ADDRESS,
};
use move_core_types::language_storage::{StructTag, TypeTag};

pub const COIN1_NAME: &str = "Coin1";
pub const COIN2_NAME: &str = "Coin2";

pub fn coin1_tag() -> TypeTag {
    TypeTag::Struct(StructTag {
        address: CORE_CODE_ADDRESS,
        module: from_currency_code_string(COIN1_NAME).unwrap(),
        name: coin_struct_name().to_owned(),
        type_params: vec![],
    })
}
<|endoftext|>


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

use autocxx::prelude::*;

include_cpp! {
    // C++ headers we want to include.
    #include "cpp.h"
    safety!(unsafe)
    generate!("MessageBuffer")
}

// A simple example dealing with plain-old-data types.

fn main() {
    moveit! {
        let mut msg = ffi::MessageBuffer::new();
    }
    msg.as_mut().add_blurb("Hello");
    msg.as_mut().add_blurb(" world!");

    assert_eq!(
        msg.get().as_ref().unwrap().to_string_lossy(),
        "Hello world!"
    );
}
<commit_msg>Fixing comments in non-trivial C++ types example.<commit_after>// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use autocxx::prelude::*;

include_cpp! {
    // C++ headers we want to include.
    #include "cpp.h"
    safety!(unsafe)
    // A non-trivial C++ type
    generate!("MessageBuffer")
}

fn main() {
    // Put the non-trivial C++ type on the Rust stack.
    moveit! { let mut msg = ffi::MessageBuffer::new(); }
    // Call methods on it.
    msg.as_mut().add_blurb("Hello");
    msg.as_mut().add_blurb(" world!");

    assert_eq!(
        msg.get().as_ref().unwrap().to_string_lossy(),
        "Hello world!"
    );
}
<|endoftext|>


<commit_before>//! Completes keywords.

use syntax::SyntaxKind;
use test_utils::mark;

use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};

pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
    // complete keyword "crate" in use stmt
    let source_range = ctx.source_range();

    if ctx.use_item_syntax.is_some() {
        if ctx.path_qual.is_none() {
            CompletionItem::new(CompletionKind::Keyword, source_range, "crate::")
                .kind(CompletionItemKind::Keyword)
                .insert_text("crate::")
                .add_to(acc);
        }
        CompletionItem::new(CompletionKind::Keyword, source_range, "self")
            .kind(CompletionItemKind::Keyword)
            .add_to(acc);
        CompletionItem::new(CompletionKind::Keyword, source_range, "super::")
            .kind(CompletionItemKind::Keyword)
            .insert_text("super::")
            .add_to(acc);
    }

    // Suggest .await syntax for types that implement Future trait
    if let Some(receiver) = &ctx.dot_receiver {
        if let Some(ty) = ctx.sema.type_of_expr(receiver) {
            if ty.impls_future(ctx.db) {
                CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
                    .kind(CompletionItemKind::Keyword)
                    .detail("expr.await")
                    .insert_text("await")
                    .add_to(acc);
            }
        };
    }
}

pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
    if ctx.token.kind() == SyntaxKind::COMMENT {
        mark::hit!(no_keyword_completion_in_comments);
        return;
    }
    if ctx.record_lit_syntax.is_some() {
        mark::hit!(no_keyword_completion_in_record_lit);
        return;
    }

    let has_trait_or_impl_parent = ctx.has_impl_parent || ctx.has_trait_parent;
    if ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling {
        add_keyword(ctx, acc, "where", "where ");
        return;
    }
    if ctx.unsafe_is_prev {
        if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent {
            add_keyword(ctx, acc, "fn", "fn $0() {}")
        }

        if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
            add_keyword(ctx, acc, "trait", "trait $0 {}");
            add_keyword(ctx, acc, "impl", "impl $0 {}");
        }

        return;
    }
    if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent
    {
        add_keyword(ctx, acc, "fn", "fn $0() {}");
    }
    if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
        add_keyword(ctx, acc, "use", "use ");
        add_keyword(ctx, acc, "impl", "impl $0 {}");
        add_keyword(ctx, acc, "trait", "trait $0 {}");
    }

    if ctx.has_item_list_or_source_file_parent {
        add_keyword(ctx, acc, "enum", "enum $0 {}");
        add_keyword(ctx, acc, "struct", "struct $0");
        add_keyword(ctx, acc, "union", "union $0 {}");
    }

    if ctx.is_expr {
        add_keyword(ctx, acc, "match", "match $0 {}");
        add_keyword(ctx, acc, "while", "while $0 {}");
        add_keyword(ctx, acc, "loop", "loop {$0}");
        add_keyword(ctx, acc, "if", "if $0 {}");
        add_keyword(ctx, acc, "if let", "if let $1 = $0 {}");
        add_keyword(ctx, acc, "for", "for $0 in $1 {}");
    }

    if ctx.if_is_prev || ctx.block_expr_parent {
        add_keyword(ctx, acc, "let", "let ");
    }

    if ctx.after_if {
        add_keyword(ctx, acc, "else", "else {$0}");
        add_keyword(ctx, acc, "else if", "else if $0 {}");
    }
    if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
        add_keyword(ctx, acc, "mod", "mod $0");
    }
    if ctx.bind_pat_parent || ctx.ref_pat_parent {
        add_keyword(ctx, acc, "mut", "mut ");
    }
    if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent
    {
        add_keyword(ctx, acc, "const", "const ");
        add_keyword(ctx, acc, "type", "type ");
    }
    if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
        add_keyword(ctx, acc, "static", "static ");
    };
    if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
        add_keyword(ctx, acc, "extern", "extern ");
    }
    if ctx.has_item_list_or_source_file_parent
        || has_trait_or_impl_parent
        || ctx.block_expr_parent
        || ctx.is_match_arm
    {
        add_keyword(ctx, acc, "unsafe", "unsafe ");
    }
    if ctx.in_loop_body {
        if ctx.can_be_stmt {
            add_keyword(ctx, acc, "continue", "continue;");
            add_keyword(ctx, acc, "break", "break;");
        } else {
            add_keyword(ctx, acc, "continue", "continue");
            add_keyword(ctx, acc, "break", "break");
        }
    }
    if ctx.has_item_list_or_source_file_parent || ctx.has_impl_parent | ctx.has_field_list_parent {
        add_keyword(ctx, acc, "pub(crate)", "pub(crate) ");
        add_keyword(ctx, acc, "pub", "pub ");
    }

    if !ctx.is_trivial_path {
        return;
    }
    let fn_def = match &ctx.function_syntax {
        Some(it) => it,
        None => return,
    };

    add_keyword(
        ctx,
        acc,
        "return",
        match (ctx.can_be_stmt, fn_def.ret_type().is_some()) {
            (true, true) => "return $0;",
            (true, false) => "return;",
            (false, true) => "return $0",
            (false, false) => "return",
        },
    )
}

fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
    let builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw)
        .kind(CompletionItemKind::Keyword);
    let builder = match ctx.config.snippet_cap {
        Some(cap) => {
            let tmp;
            let snippet = if snippet.ends_with('}') && ctx.incomplete_let {
                mark::hit!(let_semi);
                tmp = format!("{};", snippet);
                &tmp
            } else {
                snippet
            };
            builder.insert_snippet(cap, snippet)
        }
        None => builder.insert_text(if snippet.contains('$') { kw } else { snippet }),
    };
    acc.add(builder.build());
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};
    use test_utils::mark;

    use crate::{
        test_utils::{check_edit, completion_list},
        CompletionKind,
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Keyword);
        expect.assert_eq(&actual)
    }

    #[test]
    fn test_keywords_in_use_stmt() {
        check(
            r"use $0",
            expect![[r#"
                kw crate::
                kw self
                kw super::
            "#]],
        );

        check(
            r"use a::$0",
            expect![[r#"
                kw self
                kw super::
            "#]],
        );

        check(
            r"use a::{b, $0}",
            expect![[r#"
                kw self
                kw super::
            "#]],
        );
    }

    #[test]
    fn test_keywords_at_source_file_level() {
        check(
            r"m$0",
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw enum
                kw struct
                kw union
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw pub(crate)
                kw pub
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_function() {
        check(
            r"fn quux() { $0 }",
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw return
            "#]],
        );
    }

    #[test]
    fn test_keywords_inside_block() {
        check(
            r"fn quux() { if true { $0 } }",
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw return
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_if() {
        check(
            r#"fn quux() { if true { () } $0 }"#,
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw else
                kw else if
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw return
            "#]],
        );
        check_edit(
            "else",
            r#"fn quux() { if true { () } $0 }"#,
            r#"fn quux() { if true { () } else {$0} }"#,
        );
    }

    #[test]
    fn test_keywords_in_match_arm() {
        check(
            r#"
fn quux() -> i32 {
    match () { () => $0 }
}
"#,
            expect![[r#"
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw unsafe
                kw return
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_trait_def() {
        check(
            r"trait My { $0 }",
            expect![[r#"
                kw fn
                kw const
                kw type
                kw unsafe
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_impl_def() {
        check(
            r"impl My { $0 }",
            expect![[r#"
                kw fn
                kw const
                kw type
                kw unsafe
                kw pub(crate)
                kw pub
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_loop() {
        check(
            r"fn my() { loop { $0 } }",
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw continue
                kw break
                kw return
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_unsafe_in_item_list() {
        check(
            r"unsafe $0",
            expect![[r#"
                kw fn
                kw trait
                kw impl
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_unsafe_in_block_expr() {
        check(
            r"fn my_fn() { unsafe $0 }",
            expect![[r#"
                kw fn
                kw trait
                kw impl
            "#]],
        );
    }

    #[test]
    fn test_mut_in_ref_and_in_fn_parameters_list() {
        check(
            r"fn my_fn(&$0) {}",
            expect![[r#"
                kw mut
            "#]],
        );
        check(
            r"fn my_fn($0) {}",
            expect![[r#"
                kw mut
            "#]],
        );
        check(
            r"fn my_fn() { let &$0 }",
            expect![[r#"
                kw mut
            "#]],
        );
    }

    #[test]
    fn test_where_keyword() {
        check(
            r"trait A $0",
            expect![[r#"
                kw where
            "#]],
        );
        check(
            r"impl A $0",
            expect![[r#"
                kw where
            "#]],
        );
    }

    #[test]
    fn no_keyword_completion_in_comments() {
        mark::check!(no_keyword_completion_in_comments);
        check(
            r#"
fn test() {
    let x = 2; // A comment$0
}
"#,
            expect![[""]],
        );
        check(
            r#"
/*
Some multi-line comment$0
*/
"#,
            expect![[""]],
        );
        check(
            r#"
/// Some doc comment
/// let test$0 = 1
"#,
            expect![[""]],
        );
    }

    #[test]
    fn test_completion_await_impls_future() {
        check(
            r#"
//- /main.rs crate:main deps:std
use std::future::*;
struct A {}
impl Future for A {}
fn foo(a: A) { a.$0 }

//- /std/lib.rs crate:std
pub mod future {
    #[lang = "future_trait"]
    pub trait Future {}
}
"#,
            expect![[r#"
                kw await expr.await
            "#]],
        );

        check(
            r#"
//- /main.rs crate:main deps:std
use std::future::*;
fn foo() {
    let a = async {};
    a.$0
}

//- /std/lib.rs crate:std
pub mod future {
    #[lang = "future_trait"]
    pub trait Future {
        type Output;
    }
}
"#,
            expect![[r#"
                kw await expr.await
            "#]],
        )
    }

    #[test]
    fn after_let() {
        check(
            r#"fn main() { let _ = $0 }"#,
            expect![[r#"
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw return
            "#]],
        )
    }

    #[test]
    fn before_field() {
        check(
            r#"
struct Foo {
    $0
    pub f: i32,
}
"#,
            expect![[r#"
                kw pub(crate)
                kw pub
            "#]],
        )
    }

    #[test]
    fn skip_struct_initializer() {
        mark::check!(no_keyword_completion_in_record_lit);
        check(
            r#"
struct Foo {
    pub f: i32,
}
fn foo() {
    Foo {
        $0
    }
}
"#,
            expect![[r#""#]],
        );
    }

    #[test]
    fn struct_initializer_field_expr() {
        check(
            r#"
struct Foo {
    pub f: i32,
}
fn foo() {
    Foo {
        f: $0
    }
}
"#,
            expect![[r#"
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw return
            "#]],
        );
    }

    #[test]
    fn let_semi() {
        mark::check!(let_semi);
        check_edit(
            "match",
            r#"
fn main() { let x = $0 }
"#,
            r#"
fn main() { let x = match $0 {}; }
"#,
        );

        check_edit(
            "if",
            r#"
fn main() {
    let x = $0
    let y = 92;
}
"#,
            r#"
fn main() {
    let x = if $0 {};
    let y = 92;
}
"#,
        );

        check_edit(
            "loop",
            r#"
fn main() {
    let x = $0
    bar();
}
"#,
            r#"
fn main() {
    let x = loop {$0};
    bar();
}
"#,
        );
    }
}
<commit_msg>chore: swap order of placeholders<commit_after>//! Completes keywords.

use syntax::SyntaxKind;
use test_utils::mark;

use crate::{CompletionContext, CompletionItem, CompletionItemKind, CompletionKind, Completions};

pub(crate) fn complete_use_tree_keyword(acc: &mut Completions, ctx: &CompletionContext) {
    // complete keyword "crate" in use stmt
    let source_range = ctx.source_range();

    if ctx.use_item_syntax.is_some() {
        if ctx.path_qual.is_none() {
            CompletionItem::new(CompletionKind::Keyword, source_range, "crate::")
                .kind(CompletionItemKind::Keyword)
                .insert_text("crate::")
                .add_to(acc);
        }
        CompletionItem::new(CompletionKind::Keyword, source_range, "self")
            .kind(CompletionItemKind::Keyword)
            .add_to(acc);
        CompletionItem::new(CompletionKind::Keyword, source_range, "super::")
            .kind(CompletionItemKind::Keyword)
            .insert_text("super::")
            .add_to(acc);
    }

    // Suggest .await syntax for types that implement Future trait
    if let Some(receiver) = &ctx.dot_receiver {
        if let Some(ty) = ctx.sema.type_of_expr(receiver) {
            if ty.impls_future(ctx.db) {
                CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
                    .kind(CompletionItemKind::Keyword)
                    .detail("expr.await")
                    .insert_text("await")
                    .add_to(acc);
            }
        };
    }
}

pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionContext) {
    if ctx.token.kind() == SyntaxKind::COMMENT {
        mark::hit!(no_keyword_completion_in_comments);
        return;
    }
    if ctx.record_lit_syntax.is_some() {
        mark::hit!(no_keyword_completion_in_record_lit);
        return;
    }

    let has_trait_or_impl_parent = ctx.has_impl_parent || ctx.has_trait_parent;
    if ctx.trait_as_prev_sibling || ctx.impl_as_prev_sibling {
        add_keyword(ctx, acc, "where", "where ");
        return;
    }
    if ctx.unsafe_is_prev {
        if ctx.has_item_list_or_source_file_parent || ctx.block_expr_parent {
            add_keyword(ctx, acc, "fn", "fn $0() {}")
        }

        if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
            add_keyword(ctx, acc, "trait", "trait $0 {}");
            add_keyword(ctx, acc, "impl", "impl $0 {}");
        }

        return;
    }
    if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent
    {
        add_keyword(ctx, acc, "fn", "fn $0() {}");
    }
    if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
        add_keyword(ctx, acc, "use", "use ");
        add_keyword(ctx, acc, "impl", "impl $0 {}");
        add_keyword(ctx, acc, "trait", "trait $0 {}");
    }

    if ctx.has_item_list_or_source_file_parent {
        add_keyword(ctx, acc, "enum", "enum $0 {}");
        add_keyword(ctx, acc, "struct", "struct $0");
        add_keyword(ctx, acc, "union", "union $0 {}");
    }

    if ctx.is_expr {
        add_keyword(ctx, acc, "match", "match $0 {}");
        add_keyword(ctx, acc, "while", "while $0 {}");
        add_keyword(ctx, acc, "loop", "loop {$0}");
        add_keyword(ctx, acc, "if", "if $0 {}");
        add_keyword(ctx, acc, "if let", "if let $1 = $0 {}");
        add_keyword(ctx, acc, "for", "for $1 in $0 {}");
    }

    if ctx.if_is_prev || ctx.block_expr_parent {
        add_keyword(ctx, acc, "let", "let ");
    }

    if ctx.after_if {
        add_keyword(ctx, acc, "else", "else {$0}");
        add_keyword(ctx, acc, "else if", "else if $0 {}");
    }
    if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
        add_keyword(ctx, acc, "mod", "mod $0");
    }
    if ctx.bind_pat_parent || ctx.ref_pat_parent {
        add_keyword(ctx, acc, "mut", "mut ");
    }
    if ctx.has_item_list_or_source_file_parent || has_trait_or_impl_parent || ctx.block_expr_parent
    {
        add_keyword(ctx, acc, "const", "const ");
        add_keyword(ctx, acc, "type", "type ");
    }
    if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
        add_keyword(ctx, acc, "static", "static ");
    };
    if (ctx.has_item_list_or_source_file_parent) || ctx.block_expr_parent {
        add_keyword(ctx, acc, "extern", "extern ");
    }
    if ctx.has_item_list_or_source_file_parent
        || has_trait_or_impl_parent
        || ctx.block_expr_parent
        || ctx.is_match_arm
    {
        add_keyword(ctx, acc, "unsafe", "unsafe ");
    }
    if ctx.in_loop_body {
        if ctx.can_be_stmt {
            add_keyword(ctx, acc, "continue", "continue;");
            add_keyword(ctx, acc, "break", "break;");
        } else {
            add_keyword(ctx, acc, "continue", "continue");
            add_keyword(ctx, acc, "break", "break");
        }
    }
    if ctx.has_item_list_or_source_file_parent || ctx.has_impl_parent | ctx.has_field_list_parent {
        add_keyword(ctx, acc, "pub(crate)", "pub(crate) ");
        add_keyword(ctx, acc, "pub", "pub ");
    }

    if !ctx.is_trivial_path {
        return;
    }
    let fn_def = match &ctx.function_syntax {
        Some(it) => it,
        None => return,
    };

    add_keyword(
        ctx,
        acc,
        "return",
        match (ctx.can_be_stmt, fn_def.ret_type().is_some()) {
            (true, true) => "return $0;",
            (true, false) => "return;",
            (false, true) => "return $0",
            (false, false) => "return",
        },
    )
}

fn add_keyword(ctx: &CompletionContext, acc: &mut Completions, kw: &str, snippet: &str) {
    let builder = CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), kw)
        .kind(CompletionItemKind::Keyword);
    let builder = match ctx.config.snippet_cap {
        Some(cap) => {
            let tmp;
            let snippet = if snippet.ends_with('}') && ctx.incomplete_let {
                mark::hit!(let_semi);
                tmp = format!("{};", snippet);
                &tmp
            } else {
                snippet
            };
            builder.insert_snippet(cap, snippet)
        }
        None => builder.insert_text(if snippet.contains('$') { kw } else { snippet }),
    };
    acc.add(builder.build());
}

#[cfg(test)]
mod tests {
    use expect_test::{expect, Expect};
    use test_utils::mark;

    use crate::{
        test_utils::{check_edit, completion_list},
        CompletionKind,
    };

    fn check(ra_fixture: &str, expect: Expect) {
        let actual = completion_list(ra_fixture, CompletionKind::Keyword);
        expect.assert_eq(&actual)
    }

    #[test]
    fn test_keywords_in_use_stmt() {
        check(
            r"use $0",
            expect![[r#"
                kw crate::
                kw self
                kw super::
            "#]],
        );

        check(
            r"use a::$0",
            expect![[r#"
                kw self
                kw super::
            "#]],
        );

        check(
            r"use a::{b, $0}",
            expect![[r#"
                kw self
                kw super::
            "#]],
        );
    }

    #[test]
    fn test_keywords_at_source_file_level() {
        check(
            r"m$0",
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw enum
                kw struct
                kw union
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw pub(crate)
                kw pub
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_function() {
        check(
            r"fn quux() { $0 }",
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw return
            "#]],
        );
    }

    #[test]
    fn test_keywords_inside_block() {
        check(
            r"fn quux() { if true { $0 } }",
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw return
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_if() {
        check(
            r#"fn quux() { if true { () } $0 }"#,
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw else
                kw else if
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw return
            "#]],
        );
        check_edit(
            "else",
            r#"fn quux() { if true { () } $0 }"#,
            r#"fn quux() { if true { () } else {$0} }"#,
        );
    }

    #[test]
    fn test_keywords_in_match_arm() {
        check(
            r#"
fn quux() -> i32 {
    match () { () => $0 }
}
"#,
            expect![[r#"
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw unsafe
                kw return
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_trait_def() {
        check(
            r"trait My { $0 }",
            expect![[r#"
                kw fn
                kw const
                kw type
                kw unsafe
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_impl_def() {
        check(
            r"impl My { $0 }",
            expect![[r#"
                kw fn
                kw const
                kw type
                kw unsafe
                kw pub(crate)
                kw pub
            "#]],
        );
    }

    #[test]
    fn test_keywords_in_loop() {
        check(
            r"fn my() { loop { $0 } }",
            expect![[r#"
                kw fn
                kw use
                kw impl
                kw trait
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw let
                kw mod
                kw const
                kw type
                kw static
                kw extern
                kw unsafe
                kw continue
                kw break
                kw return
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_unsafe_in_item_list() {
        check(
            r"unsafe $0",
            expect![[r#"
                kw fn
                kw trait
                kw impl
            "#]],
        );
    }

    #[test]
    fn test_keywords_after_unsafe_in_block_expr() {
        check(
            r"fn my_fn() { unsafe $0 }",
            expect![[r#"
                kw fn
                kw trait
                kw impl
            "#]],
        );
    }

    #[test]
    fn test_mut_in_ref_and_in_fn_parameters_list() {
        check(
            r"fn my_fn(&$0) {}",
            expect![[r#"
                kw mut
            "#]],
        );
        check(
            r"fn my_fn($0) {}",
            expect![[r#"
                kw mut
            "#]],
        );
        check(
            r"fn my_fn() { let &$0 }",
            expect![[r#"
                kw mut
            "#]],
        );
    }

    #[test]
    fn test_where_keyword() {
        check(
            r"trait A $0",
            expect![[r#"
                kw where
            "#]],
        );
        check(
            r"impl A $0",
            expect![[r#"
                kw where
            "#]],
        );
    }

    #[test]
    fn no_keyword_completion_in_comments() {
        mark::check!(no_keyword_completion_in_comments);
        check(
            r#"
fn test() {
    let x = 2; // A comment$0
}
"#,
            expect![[""]],
        );
        check(
            r#"
/*
Some multi-line comment$0
*/
"#,
            expect![[""]],
        );
        check(
            r#"
/// Some doc comment
/// let test$0 = 1
"#,
            expect![[""]],
        );
    }

    #[test]
    fn test_completion_await_impls_future() {
        check(
            r#"
//- /main.rs crate:main deps:std
use std::future::*;
struct A {}
impl Future for A {}
fn foo(a: A) { a.$0 }

//- /std/lib.rs crate:std
pub mod future {
    #[lang = "future_trait"]
    pub trait Future {}
}
"#,
            expect![[r#"
                kw await expr.await
            "#]],
        );

        check(
            r#"
//- /main.rs crate:main deps:std
use std::future::*;
fn foo() {
    let a = async {};
    a.$0
}

//- /std/lib.rs crate:std
pub mod future {
    #[lang = "future_trait"]
    pub trait Future {
        type Output;
    }
}
"#,
            expect![[r#"
                kw await expr.await
            "#]],
        )
    }

    #[test]
    fn after_let() {
        check(
            r#"fn main() { let _ = $0 }"#,
            expect![[r#"
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw return
            "#]],
        )
    }

    #[test]
    fn before_field() {
        check(
            r#"
struct Foo {
    $0
    pub f: i32,
}
"#,
            expect![[r#"
                kw pub(crate)
                kw pub
            "#]],
        )
    }

    #[test]
    fn skip_struct_initializer() {
        mark::check!(no_keyword_completion_in_record_lit);
        check(
            r#"
struct Foo {
    pub f: i32,
}
fn foo() {
    Foo {
        $0
    }
}
"#,
            expect![[r#""#]],
        );
    }

    #[test]
    fn struct_initializer_field_expr() {
        check(
            r#"
struct Foo {
    pub f: i32,
}
fn foo() {
    Foo {
        f: $0
    }
}
"#,
            expect![[r#"
                kw match
                kw while
                kw loop
                kw if
                kw if let
                kw for
                kw return
            "#]],
        );
    }

    #[test]
    fn let_semi() {
        mark::check!(let_semi);
        check_edit(
            "match",
            r#"
fn main() { let x = $0 }
"#,
            r#"
fn main() { let x = match $0 {}; }
"#,
        );

        check_edit(
            "if",
            r#"
fn main() {
    let x = $0
    let y = 92;
}
"#,
            r#"
fn main() {
    let x = if $0 {};
    let y = 92;
}
"#,
        );

        check_edit(
            "loop",
            r#"
fn main() {
    let x = $0
    bar();
}
"#,
            r#"
fn main() {
    let x = loop {$0};
    bar();
}
"#,
        );
    }
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::collections::HashMap;
use std::str::FromStr;

use chrono::{DateTime, Utc};
use reqwest;
use serde_json::{self, Value};

use errors::*;

#[derive(Debug, Deserialize)]
pub struct Errors {
    pub detail: String,
}

#[derive(Debug, Deserialize)]
pub struct ErrorResponse {
    pub errors: Vec<Errors>,
}

impl ErrorResponse {
    pub fn detail(&self) -> &str {
        self.errors.get(0).map(|x| x.detail.as_str()).unwrap_or("")
    }
}

impl FromStr for ErrorResponse {
    type Err = Error;
    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        serde_json::from_str(s).chain_err(|| "Failed to parse JSON")
    }
}

#[derive(Debug, Deserialize)]
pub struct BadgeData {
    pub attributes: HashMap<String, Option<String>>,
    pub badge_type: String,
}

#[derive(Debug, Deserialize)]
pub struct CategoryData {
    pub category: String,
    pub crates_cnt: i32,
    pub created_at: DateTime<Utc>,
    pub description: String,
    pub id: String,
    pub slug: String,
}

#[derive(Debug, Deserialize)]
pub struct CrateLinks {
    pub version_downloads: String,
    pub versions: Option<String>,
    pub owners: Option<String>,
    pub reverse_dependencies: String,
}

#[derive(Debug, Deserialize)]
pub struct KeywordData {
    pub crates_cnt: i32,
    pub created_at: DateTime<Utc>,
    pub id: String,
    pub keyword: String,
}

#[derive(Debug, Deserialize)]
pub struct VersionLinks {
    pub authors: String,
    pub dependencies: String,
    pub version_downloads: String,
}

#[derive(Debug, Deserialize)]
pub struct VersionData {
    #[serde(rename(deserialize = "crate"))]
    pub krate: String,
    pub created_at: DateTime<Utc>,
    pub dl_path: String,
    pub downloads: i32,
    pub features: HashMap<String, Vec<String>>,
    pub id: i32,
    pub links: VersionLinks,
    pub num: String, // XXX should be semver::Version
    pub updated_at: DateTime<Utc>,
    pub yanked: bool,
}

#[derive(Debug, Deserialize)]
pub struct CrateData {
    pub badges: Option<Vec<BadgeData>>,
    pub categories: Option<Vec<String>>,
    pub created_at: DateTime<Utc>,
    pub description: Option<String>,
    pub documentation: Option<String>,
    pub downloads: i32,
    pub exact_match: bool,
    pub homepage: Option<String>,
    pub id: String,
    pub keywords: Option<Vec<String>>,
    pub license: Option<String>,
    pub links: CrateLinks,
    pub max_version: String,
    pub name: String,
    pub repository: Option<String>,
    pub updated_at: DateTime<Utc>,
    pub versions: Option<Vec<i32>>,
}

#[derive(Debug, Deserialize)]
pub struct ApiResponse {
    pub categories: Vec<CategoryData>,
    #[serde(rename(deserialize = "crate"))]
    pub krate: CrateData,
    pub keywords: Vec<KeywordData>,
    pub versions: Vec<VersionData>,
}

impl FromStr for ApiResponse {
    type Err = Error;
    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        serde_json::from_str(s).chain_err(|| "Failed to parse JSON")
    }
}

#[derive(Debug)]
pub struct CratesIO {
    response: reqwest::Response,
    body: String,
}

impl CratesIO {
    pub fn query(krate: &str) -> Result<Self> {
        let url = format!("https://crates.io/api/v1/crates/{}", krate);
        let mut response = reqwest::get(&url)?;
        let mut body = String::with_capacity(20480);
        response.read_to_string(&mut body)?;
        Ok(CratesIO {
            response: response,
            body: body,
        })
    }

    pub fn raw_data(&self) -> &str {
        &self.body
    }

    pub fn as_json(&self) -> Result<Value> {
        serde_json::from_str(&self.body).chain_err(|| "Failed to parse JSON")
        // serde_json::to_string_pretty(&json).chain_err(|| "Failed to prettify")
    }

    pub fn as_data(&self) -> Result<ApiResponse> {
        if *self.response.status() == reqwest::StatusCode::Ok {
            self.body.parse::<ApiResponse>()
        } else {
            self.body
                .parse::<ErrorResponse>()
                .and_then(|er| Err(ErrorKind::CratesIOError(er).into()))
        }
    }
}
<commit_msg>Add onwer_team and owner_user fields<commit_after>use std::io::Read;
use std::collections::HashMap;
use std::str::FromStr;

use chrono::{DateTime, Utc};
use reqwest;
use serde_json::{self, Value};

use errors::*;

#[derive(Debug, Deserialize)]
pub struct Errors {
    pub detail: String,
}

#[derive(Debug, Deserialize)]
pub struct ErrorResponse {
    pub errors: Vec<Errors>,
}

impl ErrorResponse {
    pub fn detail(&self) -> &str {
        self.errors.get(0).map(|x| x.detail.as_str()).unwrap_or("")
    }
}

impl FromStr for ErrorResponse {
    type Err = Error;
    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        serde_json::from_str(s).chain_err(|| "Failed to parse JSON")
    }
}

#[derive(Debug, Deserialize)]
pub struct BadgeData {
    pub attributes: HashMap<String, Option<String>>,
    pub badge_type: String,
}

#[derive(Debug, Deserialize)]
pub struct CategoryData {
    pub category: String,
    pub crates_cnt: i32,
    pub created_at: DateTime<Utc>,
    pub description: String,
    pub id: String,
    pub slug: String,
}

#[derive(Debug, Deserialize)]
pub struct CrateLinks {
    pub version_downloads: String,
    pub versions: Option<String>,
    pub owners: Option<String>,
    pub reverse_dependencies: String,
    pub owner_team: Option<String>,
    pub owner_user: Option<String>,
}

#[derive(Debug, Deserialize)]
pub struct KeywordData {
    pub crates_cnt: i32,
    pub created_at: DateTime<Utc>,
    pub id: String,
    pub keyword: String,
}

#[derive(Debug, Deserialize)]
pub struct VersionLinks {
    pub authors: String,
    pub dependencies: String,
    pub version_downloads: String,
}

#[derive(Debug, Deserialize)]
pub struct VersionData {
    #[serde(rename(deserialize = "crate"))]
    pub krate: String,
    pub created_at: DateTime<Utc>,
    pub dl_path: String,
    pub downloads: i32,
    pub features: HashMap<String, Vec<String>>,
    pub id: i32,
    pub links: VersionLinks,
    pub num: String, // XXX should be semver::Version
    pub updated_at: DateTime<Utc>,
    pub yanked: bool,
}

#[derive(Debug, Deserialize)]
pub struct CrateData {
    pub badges: Option<Vec<BadgeData>>,
    pub categories: Option<Vec<String>>,
    pub created_at: DateTime<Utc>,
    pub description: Option<String>,
    pub documentation: Option<String>,
    pub downloads: i32,
    pub exact_match: bool,
    pub homepage: Option<String>,
    pub id: String,
    pub keywords: Option<Vec<String>>,
    pub license: Option<String>,
    pub links: CrateLinks,
    pub max_version: String,
    pub name: String,
    pub repository: Option<String>,
    pub updated_at: DateTime<Utc>,
    pub versions: Option<Vec<i32>>,
}

#[derive(Debug, Deserialize)]
pub struct ApiResponse {
    pub categories: Vec<CategoryData>,
    #[serde(rename(deserialize = "crate"))]
    pub krate: CrateData,
    pub keywords: Vec<KeywordData>,
    pub versions: Vec<VersionData>,
}

impl FromStr for ApiResponse {
    type Err = Error;
    fn from_str(s: &str) -> ::std::result::Result<Self, Self::Err> {
        serde_json::from_str(s).chain_err(|| "Failed to parse JSON")
    }
}

#[derive(Debug)]
pub struct CratesIO {
    response: reqwest::Response,
    body: String,
}

impl CratesIO {
    pub fn query(krate: &str) -> Result<Self> {
        let url = format!("https://crates.io/api/v1/crates/{}", krate);
        let mut response = reqwest::get(&url)?;
        let mut body = String::with_capacity(20480);
        response.read_to_string(&mut body)?;
        Ok(CratesIO {
            response: response,
            body: body,
        })
    }

    pub fn raw_data(&self) -> &str {
        &self.body
    }

    pub fn as_json(&self) -> Result<Value> {
        serde_json::from_str(&self.body).chain_err(|| "Failed to parse JSON")
        // serde_json::to_string_pretty(&json).chain_err(|| "Failed to prettify")
    }

    pub fn as_data(&self) -> Result<ApiResponse> {
        if *self.response.status() == reqwest::StatusCode::Ok {
            self.body.parse::<ApiResponse>()
        } else {
            self.body
                .parse::<ErrorResponse>()
                .and_then(|er| Err(ErrorKind::CratesIOError(er).into()))
        }
    }
}
<|endoftext|>


<commit_before>use quote::{ToTokens, Tokens};

use metadata::Metadata;
use parse::Entry;
use request::Request;
use response::Response;

#[derive(Debug)]
pub struct Api {
    metadata: Metadata,
    request: Request,
    response: Response,
}

impl ToTokens for Api {
    fn to_tokens(&self, tokens: &mut Tokens) {
        let description = &self.metadata.description;
        let method = &self.metadata.method;
        let name = &self.metadata.name;
        let path = &self.metadata.path;
        let rate_limited = &self.metadata.rate_limited;
        let requires_authentication = &self.metadata.requires_authentication;

        let request_types = {
            let mut tokens = Tokens::new();
            self.request.to_tokens(&mut tokens);
            tokens
        };
        let response_types = {
            let mut tokens = Tokens::new();
            self.response.to_tokens(&mut tokens);
            tokens
        };

        let add_body_to_request = if self.request.has_body_fields() {
            let request_body_init_fields = self.request.request_body_init_fields();

            quote! {
                let request_body = RequestBody {
                    #request_body_init_fields
                };

                hyper_request.set_body(::serde_json::to_vec(&request_body)?);
            }
        } else {
            Tokens::new()
        };

        let deserialize_response_body = if self.response.has_body_fields() {
            let mut tokens = Tokens::new();

            tokens.append(quote! {
                let future_response = hyper_response.body()
                    .fold::<_, _, Result<_, ::std::io::Error>>(Vec::new(), |mut bytes, chunk| {
                        bytes.write_all(&chunk)?;

                        Ok(bytes)
                    })
                    .map_err(::ruma_api::Error::from)
                    .and_then(|bytes| {
                        ::serde_json::from_slice::<ResponseBody>(bytes.as_slice())
                            .map_err(::ruma_api::Error::from)
                    })
            });

            tokens.append(".and_then(|response_body| {");

            tokens
        } else {
            let mut tokens = Tokens::new();

            tokens.append(quote! {
                let future_response = ::futures::future::ok(())
            });

            tokens.append(".and_then(|_| {");

            tokens
        };

        let mut closure_end = Tokens::new();
        closure_end.append("});");

        let response_init_fields = if self.response.has_fields() {
            self.response.init_fields()
        } else {
            Tokens::new()
        };

        tokens.append(quote! {
            use std::io::Write as _Write;

            use ::futures::{Future as _Future, Stream as _Stream};
            use ::ruma_api::Endpoint as _RumaApiEndpoint;

            /// The API endpoint.
            #[derive(Debug)]
            pub struct Endpoint;

            #request_types

            impl ::std::convert::TryFrom<Request> for ::hyper::Request {
                type Error = ::ruma_api::Error;

                #[allow(unused_mut, unused_variables)]
                fn try_from(request: Request) -> Result<Self, Self::Error> {
                    let metadata = Endpoint::METADATA;

                    let mut hyper_request = ::hyper::Request::new(
                        metadata.method,
                        metadata.path.parse()?,
                    );

                    #add_body_to_request

                    Ok(hyper_request)
                }
            }

            #response_types

            impl ::futures::future::FutureFrom<::hyper::Response> for Response {
                type Future = Box<_Future<Item = Self, Error = Self::Error>>;
                type Error = ::ruma_api::Error;

                fn future_from(hyper_response: ::hyper::Response)
                -> Box<_Future<Item = Self, Error = Self::Error>> {
                    #deserialize_response_body

                    let response = Response {
                        #response_init_fields
                    };

                    Ok(response)
                    #closure_end

                    Box::new(future_response)
                }
            }

            impl ::ruma_api::Endpoint for Endpoint {
                type Request = Request;
                type Response = Response;

                const METADATA: ::ruma_api::Metadata = ::ruma_api::Metadata {
                    description: #description,
                    method: ::hyper::#method,
                    name: #name,
                    path: #path,
                    rate_limited: #rate_limited,
                    requires_authentication: #requires_authentication,
                };
            }
        });
    }
}

impl From<Vec<Entry>> for Api {
    fn from(entries: Vec<Entry>) -> Api {
        if entries.len() != 3 {
            panic!("ruma_api! expects 3 blocks: metadata, request, and response");
        }

        let mut metadata = None;
        let mut request = None;
        let mut response = None;

        for entry in entries {
            match entry {
                Entry::Metadata(fields) => metadata = Some(Metadata::from(fields)),
                Entry::Request(fields) => request = Some(Request::from(fields)),
                Entry::Response(fields) => response = Some(Response::from(fields)),
            }
        }

        Api {
            metadata: metadata.expect("ruma_api! is missing metadata"),
            request: request.expect("ruma_api! is missing request"),
            response: response.expect("ruma_api! is missing response"),
        }
    }
}
<commit_msg>Silence warnings for conditionally used traits and variables.<commit_after>use quote::{ToTokens, Tokens};

use metadata::Metadata;
use parse::Entry;
use request::Request;
use response::Response;

#[derive(Debug)]
pub struct Api {
    metadata: Metadata,
    request: Request,
    response: Response,
}

impl ToTokens for Api {
    fn to_tokens(&self, tokens: &mut Tokens) {
        let description = &self.metadata.description;
        let method = &self.metadata.method;
        let name = &self.metadata.name;
        let path = &self.metadata.path;
        let rate_limited = &self.metadata.rate_limited;
        let requires_authentication = &self.metadata.requires_authentication;

        let request_types = {
            let mut tokens = Tokens::new();
            self.request.to_tokens(&mut tokens);
            tokens
        };
        let response_types = {
            let mut tokens = Tokens::new();
            self.response.to_tokens(&mut tokens);
            tokens
        };

        let add_body_to_request = if self.request.has_body_fields() {
            let request_body_init_fields = self.request.request_body_init_fields();

            quote! {
                let request_body = RequestBody {
                    #request_body_init_fields
                };

                hyper_request.set_body(::serde_json::to_vec(&request_body)?);
            }
        } else {
            Tokens::new()
        };

        let deserialize_response_body = if self.response.has_body_fields() {
            let mut tokens = Tokens::new();

            tokens.append(quote! {
                let future_response = hyper_response.body()
                    .fold::<_, _, Result<_, ::std::io::Error>>(Vec::new(), |mut bytes, chunk| {
                        bytes.write_all(&chunk)?;

                        Ok(bytes)
                    })
                    .map_err(::ruma_api::Error::from)
                    .and_then(|bytes| {
                        ::serde_json::from_slice::<ResponseBody>(bytes.as_slice())
                            .map_err(::ruma_api::Error::from)
                    })
            });

            tokens.append(".and_then(|response_body| {");

            tokens
        } else {
            let mut tokens = Tokens::new();

            tokens.append(quote! {
                let future_response = ::futures::future::ok(())
            });

            tokens.append(".and_then(|_| {");

            tokens
        };

        let mut closure_end = Tokens::new();
        closure_end.append("});");

        let response_init_fields = if self.response.has_fields() {
            self.response.init_fields()
        } else {
            Tokens::new()
        };

        tokens.append(quote! {
            #[allow(unused_imports)]
            use std::io::Write as _Write;

            #[allow(unused_imports)]
            use ::futures::{Future as _Future, Stream as _Stream};
            use ::ruma_api::Endpoint as _RumaApiEndpoint;

            /// The API endpoint.
            #[derive(Debug)]
            pub struct Endpoint;

            #request_types

            impl ::std::convert::TryFrom<Request> for ::hyper::Request {
                type Error = ::ruma_api::Error;

                #[allow(unused_mut, unused_variables)]
                fn try_from(request: Request) -> Result<Self, Self::Error> {
                    let metadata = Endpoint::METADATA;

                    let mut hyper_request = ::hyper::Request::new(
                        metadata.method,
                        metadata.path.parse()?,
                    );

                    #add_body_to_request

                    Ok(hyper_request)
                }
            }

            #response_types

            impl ::futures::future::FutureFrom<::hyper::Response> for Response {
                type Future = Box<_Future<Item = Self, Error = Self::Error>>;
                type Error = ::ruma_api::Error;

                #[allow(unused_variables)]
                fn future_from(hyper_response: ::hyper::Response)
                -> Box<_Future<Item = Self, Error = Self::Error>> {
                    #deserialize_response_body

                    let response = Response {
                        #response_init_fields
                    };

                    Ok(response)
                    #closure_end

                    Box::new(future_response)
                }
            }

            impl ::ruma_api::Endpoint for Endpoint {
                type Request = Request;
                type Response = Response;

                const METADATA: ::ruma_api::Metadata = ::ruma_api::Metadata {
                    description: #description,
                    method: ::hyper::#method,
                    name: #name,
                    path: #path,
                    rate_limited: #rate_limited,
                    requires_authentication: #requires_authentication,
                };
            }
        });
    }
}

impl From<Vec<Entry>> for Api {
    fn from(entries: Vec<Entry>) -> Api {
        if entries.len() != 3 {
            panic!("ruma_api! expects 3 blocks: metadata, request, and response");
        }

        let mut metadata = None;
        let mut request = None;
        let mut response = None;

        for entry in entries {
            match entry {
                Entry::Metadata(fields) => metadata = Some(Metadata::from(fields)),
                Entry::Request(fields) => request = Some(Request::from(fields)),
                Entry::Response(fields) => response = Some(Response::from(fields)),
            }
        }

        Api {
            metadata: metadata.expect("ruma_api! is missing metadata"),
            request: request.expect("ruma_api! is missing request"),
            response: response.expect("ruma_api! is missing response"),
        }
    }
}
<|endoftext|>


<commit_before>//! Common code of `build.rs` of two tests

pub use protobuf_codegen::Customize;

use std::io::Write;
use std::io::Read;
use std::io::BufRead;
use std::io::BufReader;
use std::fs;
use std::fmt;
use std::path::Path;

use glob;

pub fn glob_simple(pattern: &str) -> Vec<String> {
    let mut r: Vec<_> = glob::glob(pattern)
        .expect("glob")
        .map(|g| {
            g.expect("item")
                .as_path()
                .to_str()
                .expect("utf-8")
                .to_owned()
        })
        .collect();
    // Make test stable
    r.sort();
    r
}

fn read_gitignore(dir: &Path) -> Vec<String> {
    let mut patterns = Vec::new();

    let gitignore = format!("{}/.gitignore", dir.display());
    let gitignore = &Path::new(&gitignore);
    if gitignore.exists() {
        let gitignore = fs::File::open(gitignore)
            .expect(&format!("open gitignore {:?}", gitignore));
        for line in BufReader::new(gitignore).lines() {
            let line = line.expect("read_line");
            if line.is_empty() || line.starts_with("#") {
                continue;
            }
            patterns.push(line);
        }
    }

    patterns
}

fn clean_recursively(dir: &Path, patterns: &[&str]) {
    assert!(dir.is_dir());

    let gitignore_patterns = read_gitignore(dir);

    let mut patterns = patterns.to_vec();
    patterns.extend(gitignore_patterns.iter().map(String::as_str));

    let patterns_compiled: Vec<_> = patterns.iter()
        .map(|&p| glob::Pattern::new(p).expect("failed to compile pattern"))
        .collect();

    for entry in fs::read_dir(dir).expect("read_dir") {
        let entry = entry.expect("entry");
        let entry_path = entry.path();
        let file_name = entry_path.as_path().file_name().unwrap().to_str().unwrap();
        if entry.metadata().expect(&format!("metadata of {:?}", entry_path)).is_dir() {
            clean_recursively(&entry_path, &patterns);
        } else if file_name == ".gitignore" {
            // keep it
        } else {
            for pattern in &patterns_compiled {
                if pattern.matches(file_name) {
                    fs::remove_file(&entry_path).expect(&format!("remove_file {:?}", entry_path));
                    break;
                }
            }
        }
    }
}

pub fn clean_old_files() {
    clean_recursively(&Path::new("src"), &["*_pb.rs", "*_pb_proto3.rs"]);
}

#[derive(Default)]
pub struct GenInDirArgs<'a> {
    pub out_dir: &'a str,
    pub input: &'a [&'a str],
    pub includes: &'a [&'a str],
    pub customize: Customize,
}

/// Generate mod.rs from all files in a directory
pub fn gen_mod_rs_in_dir(dir: &str) {
    assert!(Path::new(dir).is_dir());

    let mut mod_rs = fs::File::create(&format!("{}/mod.rs", dir)).expect("create");

    writeln!(mod_rs, "// generated by {}", module_path!()).expect("write");
    writeln!(mod_rs, "").expect("write");

    let rs_files = glob_simple(&format!("{}/*.rs", dir));

    for rs in rs_files {
        let file_name = Path::new(&rs).file_name().expect("file_name").to_str().expect("file_name");
        if file_name == "mod.rs" {
            continue;
        }
        assert!(file_name.ends_with(".rs"));
        let mod_name = &file_name[..file_name.len() - ".rs".len()];

        if mod_name.contains("carllerche") {
            writeln!(mod_rs, r#"#[cfg(feature = "with-bytes")]"#).expect("write");
        }
        writeln!(mod_rs, "mod {};", mod_name).expect("write");
    }

    mod_rs.flush().expect("flush");
}

enum TestProtobufVersions {
    V2,
    V3,
    Google,
}

#[derive(Eq, PartialEq, Debug)]
enum ProtobufSyntax {
    V2,
    V3,
}

fn test_version_from_file_path(mut file_path: &Path) -> TestProtobufVersions {
    loop {
        let name = file_path.file_name().expect("file_name").to_str().expect("to_str");
        if name == "v2" {
            return TestProtobufVersions::V2;
        } else if name == "v3" {
            return TestProtobufVersions::V3;
        } else if name == "google" {
            return TestProtobufVersions::Google;
        }

        file_path = file_path.parent().expect("parent");
    }
}

fn test_version_from_file_content(file_path: &Path) -> ProtobufSyntax {
    let content = fs::read_to_string(file_path)
        .expect(&format!("read_to_string {:?}", file_path));
    if content.contains("syntax = \"proto2\"") {
        return ProtobufSyntax::V2;
    } else if content.contains("syntax = \"proto3\"") {
        return ProtobufSyntax::V3;
    } else {
        panic!("cannot detect protobuf version from file content: {:?}", file_path);
    }
}

fn check_test_version(file_path: &Path) {
    let expected_version_from_file_name = match test_version_from_file_path(file_path) {
        TestProtobufVersions::V2 => ProtobufSyntax::V2,
        TestProtobufVersions::V3 => ProtobufSyntax::V3,
        TestProtobufVersions::Google => return,
    };

    let version = test_version_from_file_content(file_path);
    assert_eq!(expected_version_from_file_name, version, "for file: {:?}", file_path);
}

pub fn gen_in_dir_impl<F, E>(dir: &str, include_dir: &str, gen: F)
    where
        F : for<'a> Fn(GenInDirArgs<'a>) -> Result<(), E>,
        E : fmt::Debug,
{
    info!("generating protos in {}", dir);

    let mut protos = Vec::new();
    for suffix in &[".proto", ".proto3"] {
        protos.extend(glob_simple(&format!("{}/*{}", dir, suffix)));
    }

    for file_path in &protos {
        check_test_version(Path::new(file_path));
    }

    assert!(!protos.is_empty(), "no protos found in {}", dir);

    let includes = ["../proto", include_dir];

    eprintln!("invoking protobubf compiler: out_dir: {:?}, input: {:?}, includes: {:?}",
        dir, protos, includes);

    gen(GenInDirArgs {
        out_dir: dir,
        input: &protos.iter().map(|a| a.as_ref()).collect::<Vec<&str>>(),
        includes: &includes,
        .. Default::default()
    }).expect("codegen failed");

    gen_mod_rs_in_dir(dir);
}

pub fn list_tests_in_dir(dir: &str) -> Vec<String> {
    let mut r = Vec::new();
    for entry in fs::read_dir(dir).expect("read_dir") {
        let entry = entry.expect("entry");
        let entry_path = entry.path();
        let file_name = entry_path.as_path().file_name().unwrap().to_str().unwrap();

        // temporart files
        if file_name.ends_with(".") {
            continue;
        }

        if !file_name.ends_with(".rs") || file_name.ends_with("_pb.rs") {
            continue;
        }

        if file_name == "mod.rs" {
            continue;
        }

        r.push(file_name[..file_name.len() - ".rs".len()].to_owned());
    }

    // Make test stable
    r.sort();

    r
}

pub fn copy_tests_v2_v3(v2_dir: &str, v3_dir: &str) {
    for test_name in list_tests_in_dir(v2_dir) {
        let mut p2f = fs::File::open(&format!("{}/{}_pb.proto", v2_dir, test_name))
            .expect("open v2 .proto");
        let mut proto = String::new();
        p2f.read_to_string(&mut proto).expect("read .proto");
        drop(p2f);

        let mut r2f = fs::File::open(&format!("{}/{}.rs", v2_dir, test_name))
            .expect("open v2 .rs");
        let mut rs = String::new();
        r2f.read_to_string(&mut rs).expect("read .rs");
        drop(r2f);

        let mut p3f = fs::File::create(&format!("{}/{}_pb.proto", v3_dir, test_name))
            .expect("create v3 .proto");
        let mut r3f = fs::File::create(&format!("{}/{}.rs", v3_dir, test_name))
            .expect("create v3 .rs");

        // convert proto2 to proto3
        let proto = proto.replace("optional ", "");
        let proto = proto.replace("required ", "");
        let proto = proto.replace("syntax = \"proto2\";", "syntax = \"proto3\";");
        write!(p3f, "// generated\n").expect("write");
        write!(p3f, "{}", proto).expect("write");
        p3f.flush().expect("flush");

        write!(r3f, "// generated\n").expect("write");
        write!(r3f, "{}", rs).expect("write");
        r3f.flush().expect("flush");
    }
}
<commit_msg>More diagnostics<commit_after>//! Common code of `build.rs` of two tests

pub use protobuf_codegen::Customize;

use std::io::Write;
use std::io::Read;
use std::io::BufRead;
use std::io::BufReader;
use std::fs;
use std::fmt;
use std::path::Path;

use glob;

pub fn glob_simple(pattern: &str) -> Vec<String> {
    let mut r: Vec<_> = glob::glob(pattern)
        .expect("glob")
        .map(|g| {
            g.expect("item")
                .as_path()
                .to_str()
                .expect("utf-8")
                .to_owned()
        })
        .collect();
    // Make test stable
    r.sort();
    r
}

fn read_gitignore(dir: &Path) -> Vec<String> {
    let mut patterns = Vec::new();

    let gitignore = format!("{}/.gitignore", dir.display());
    let gitignore = &Path::new(&gitignore);
    if gitignore.exists() {
        let gitignore = fs::File::open(gitignore)
            .expect(&format!("open gitignore {:?}", gitignore));
        for line in BufReader::new(gitignore).lines() {
            let line = line.expect("read_line");
            if line.is_empty() || line.starts_with("#") {
                continue;
            }
            patterns.push(line);
        }
    }

    patterns
}

fn clean_recursively(dir: &Path, patterns: &[&str]) {
    assert!(dir.is_dir());

    eprintln!("cleaning ignored files in {:?}", dir);

    let gitignore_patterns = read_gitignore(dir);

    let mut patterns = patterns.to_vec();
    patterns.extend(gitignore_patterns.iter().map(String::as_str));

    let patterns_compiled: Vec<_> = patterns.iter()
        .map(|&p| glob::Pattern::new(p).expect("failed to compile pattern"))
        .collect();

    for entry in fs::read_dir(dir).expect("read_dir") {
        let entry = entry.expect("entry");
        let entry_path = entry.path();
        let file_name = entry_path.as_path().file_name().unwrap().to_str().unwrap();
        if entry.metadata().expect(&format!("metadata of {:?}", entry_path)).is_dir() {
            clean_recursively(&entry_path, &patterns);
        } else if file_name == ".gitignore" {
            // keep it
        } else {
            for pattern in &patterns_compiled {
                if pattern.matches(file_name) {
                    fs::remove_file(&entry_path).expect(&format!("remove_file {:?}", entry_path));
                    break;
                }
            }
        }
    }
}

pub fn clean_old_files() {
    clean_recursively(&Path::new("src"), &["*_pb.rs", "*_pb_proto3.rs"]);
}

#[derive(Default)]
pub struct GenInDirArgs<'a> {
    pub out_dir: &'a str,
    pub input: &'a [&'a str],
    pub includes: &'a [&'a str],
    pub customize: Customize,
}

/// Generate mod.rs from all files in a directory
pub fn gen_mod_rs_in_dir(dir: &str) {
    assert!(Path::new(dir).is_dir());

    let mut mod_rs = fs::File::create(&format!("{}/mod.rs", dir)).expect("create");

    writeln!(mod_rs, "// generated by {}", module_path!()).expect("write");
    writeln!(mod_rs, "").expect("write");

    let rs_files = glob_simple(&format!("{}/*.rs", dir));

    for rs in rs_files {
        let file_name = Path::new(&rs).file_name().expect("file_name").to_str().expect("file_name");
        if file_name == "mod.rs" {
            continue;
        }
        assert!(file_name.ends_with(".rs"));
        let mod_name = &file_name[..file_name.len() - ".rs".len()];

        if mod_name.contains("carllerche") {
            writeln!(mod_rs, r#"#[cfg(feature = "with-bytes")]"#).expect("write");
        }
        writeln!(mod_rs, "mod {};", mod_name).expect("write");
    }

    mod_rs.flush().expect("flush");
}

enum TestProtobufVersions {
    V2,
    V3,
    Google,
}

#[derive(Eq, PartialEq, Debug)]
enum ProtobufSyntax {
    V2,
    V3,
}

fn test_version_from_file_path(mut file_path: &Path) -> TestProtobufVersions {
    loop {
        let name = file_path.file_name().expect("file_name").to_str().expect("to_str");
        if name == "v2" {
            return TestProtobufVersions::V2;
        } else if name == "v3" {
            return TestProtobufVersions::V3;
        } else if name == "google" {
            return TestProtobufVersions::Google;
        }

        file_path = file_path.parent().expect("parent");
    }
}

fn test_version_from_file_content(file_path: &Path) -> ProtobufSyntax {
    let content = fs::read_to_string(file_path)
        .expect(&format!("read_to_string {:?}", file_path));
    if content.contains("syntax = \"proto2\"") {
        return ProtobufSyntax::V2;
    } else if content.contains("syntax = \"proto3\"") {
        return ProtobufSyntax::V3;
    } else {
        panic!("cannot detect protobuf version from file content: {:?}", file_path);
    }
}

fn check_test_version(file_path: &Path) {
    let expected_version_from_file_name = match test_version_from_file_path(file_path) {
        TestProtobufVersions::V2 => ProtobufSyntax::V2,
        TestProtobufVersions::V3 => ProtobufSyntax::V3,
        TestProtobufVersions::Google => return,
    };

    let version = test_version_from_file_content(file_path);
    assert_eq!(expected_version_from_file_name, version, "for file: {:?}", file_path);
}

pub fn gen_in_dir_impl<F, E>(dir: &str, include_dir: &str, gen: F)
    where
        F : for<'a> Fn(GenInDirArgs<'a>) -> Result<(), E>,
        E : fmt::Debug,
{
    info!("generating protos in {}", dir);

    let mut protos = Vec::new();
    for suffix in &[".proto", ".proto3"] {
        protos.extend(glob_simple(&format!("{}/*{}", dir, suffix)));
    }

    for file_path in &protos {
        check_test_version(Path::new(file_path));
    }

    assert!(!protos.is_empty(), "no protos found in {}", dir);

    let includes = ["../proto", include_dir];

    eprintln!("invoking protobubf compiler: out_dir: {:?}, input: {:?}, includes: {:?}",
        dir, protos, includes);

    gen(GenInDirArgs {
        out_dir: dir,
        input: &protos.iter().map(|a| a.as_ref()).collect::<Vec<&str>>(),
        includes: &includes,
        .. Default::default()
    }).expect("codegen failed");

    gen_mod_rs_in_dir(dir);
}

pub fn list_tests_in_dir(dir: &str) -> Vec<String> {
    let mut r = Vec::new();
    for entry in fs::read_dir(dir).expect("read_dir") {
        let entry = entry.expect("entry");
        let entry_path = entry.path();
        let file_name = entry_path.as_path().file_name().unwrap().to_str().unwrap();

        // temporart files
        if file_name.ends_with(".") {
            continue;
        }

        if !file_name.ends_with(".rs") || file_name.ends_with("_pb.rs") {
            continue;
        }

        if file_name == "mod.rs" {
            continue;
        }

        r.push(file_name[..file_name.len() - ".rs".len()].to_owned());
    }

    // Make test stable
    r.sort();

    r
}

pub fn copy_tests_v2_v3(v2_dir: &str, v3_dir: &str) {
    for test_name in list_tests_in_dir(v2_dir) {
        let mut p2f = fs::File::open(&format!("{}/{}_pb.proto", v2_dir, test_name))
            .expect("open v2 .proto");
        let mut proto = String::new();
        p2f.read_to_string(&mut proto).expect("read .proto");
        drop(p2f);

        let mut r2f = fs::File::open(&format!("{}/{}.rs", v2_dir, test_name))
            .expect("open v2 .rs");
        let mut rs = String::new();
        r2f.read_to_string(&mut rs).expect("read .rs");
        drop(r2f);

        let mut p3f = fs::File::create(&format!("{}/{}_pb.proto", v3_dir, test_name))
            .expect("create v3 .proto");
        let mut r3f = fs::File::create(&format!("{}/{}.rs", v3_dir, test_name))
            .expect("create v3 .rs");

        // convert proto2 to proto3
        let proto = proto.replace("optional ", "");
        let proto = proto.replace("required ", "");
        let proto = proto.replace("syntax = \"proto2\";", "syntax = \"proto3\";");
        write!(p3f, "// generated\n").expect("write");
        write!(p3f, "{}", proto).expect("write");
        p3f.flush().expect("flush");

        write!(r3f, "// generated\n").expect("write");
        write!(r3f, "{}", rs).expect("write");
        r3f.flush().expect("flush");
    }
}
<|endoftext|>