<commit_before>use business::db::Db;
use entities::*;
use rusted_cypher::GraphClient;
use business::error::RepoError;
use std::result;

type Result<T> = result::Result<T, RepoError>;

fn neo4j_edge_name(t: &Triple) -> &str {
    match t.predicate {
       Relation::IsTaggedWith    => "IS_TAGGED_WITH",
       Relation::IsRatedWith     => "IS_RATED_WITH",
       Relation::IsCommentedWith => "IS_COMMENTED_WITH",
       Relation::CreatedBy       => "CREATED_BY"
    }.into()
}

fn object_id_to_neo4j_label(id: &ObjectId) -> (&str,&str) {
    match *id {
        ObjectId::Entry(ref id) => ("Entry",id),
        ObjectId::Tag(ref id) => ("Tag",id),
        ObjectId::User(ref id) => ("User",id),
        ObjectId::Comment(ref id) => ("Comment",id),
        ObjectId::Rating(ref id) => ("Rating",id)
    }
}

fn neo4j_label_to_object_id(label: &str, id: String) -> Option<ObjectId> {
    match label {
        "Entry"     => Some(ObjectId::Entry(id)),
        "Tag"       => Some(ObjectId::Tag(id)),
        "User"      => Some(ObjectId::User(id)),
        "Comment"   => Some(ObjectId::Comment(id)),
        "Rating"    => Some(ObjectId::Rating(id)),
        _           => None,
    }
}

fn neo4j_relation_to_relation(rel: &str) -> Option<Relation> {
    match rel {
        "IS_TAGGED_WITH"    => Some(Relation::IsTaggedWith),
        "IS_RATED_WITH"     => Some(Relation::IsRatedWith),
        "IS_COMMENTED_WITH" => Some(Relation::IsCommentedWith),
        "CREATED_BY"        => Some(Relation::CreatedBy),
        _                   => None
    }
}

#[derive(Deserialize,Debug)]
struct Neo4jObj {
    labels: Vec<String>,
    id: String
}

#[derive(Deserialize,Debug)]
struct Neo4jTriple {
    subject: Neo4jObj,
    predicate: String,
    object: Neo4jObj
}

fn from_neo_triple(t: Neo4jTriple) -> Option<Triple> {
    if t.subject.labels.is_empty() || t.object.labels.is_empty() {
        warn!("No labels found in {:?}", t);
        return None;
    }
    let subject = neo4j_label_to_object_id(&t.subject.labels[0], t.subject.id);
    let predicate = neo4j_relation_to_relation(&t.predicate);
    let object = neo4j_label_to_object_id(&t.object.labels[0], t.object.id);

    if let (Some(s), Some(p), Some(o)) = (subject, predicate, object) {
        Some(Triple {
            subject: s,
            predicate: p,
            object: o
        })
    } else {
        None
    }
}

impl Db for GraphClient {
    fn get_entry(&self, id: &str) -> Result<Entry> {
        let result = self.exec(cypher_stmt!(
        "MATCH (e:Entry)<--(s:EntryState) WHERE e.id = {id}
         WITH max(s.version) as version
         MATCH (e:Entry)<--(s:EntryState)
         WHERE e.id = {id} AND s.version = version
         WITH e, s
         MATCH s<-[:BELONGS_TO]-(c:Category)
         WITH e, s, collect(DISTINCT c.id) as categories
         RETURN {
           id          : e.id,
           created     : s.created,
           version     : s.version,
           title       : s.title,
           description : s.description,
           lat         : s.lat,
           lng         : s.lng,
           street      : s.street,
           zip         : s.zip,
           city        : s.city,
           country     : s.country,
           email       : s.email,
           telephone   : s.telephone,
           homepage    : s.homepage,
           categories  : categories,
           license     : s.license
         } AS e
         ORDER BY e.created DESC", {"id" => &id})?)?;
        let r = result.rows().next().ok_or(RepoError::NotFound)?;
        let e = r.get::<Entry>("e")?;
        Ok(e)
    }

    fn get_user(&self, username: &str) -> Result<User> {
        let result = self.exec(cypher_stmt!(
        "MATCH (u:User)
         WHERE u.username = {username}
         RETURN u",
        { "username" => username })?)?;
        let r = result.rows().next().ok_or(RepoError::NotFound)?;
        let u = r.get::<User>("u")?;
        Ok(u)
    }

    fn all_entries(&self) -> Result<Vec<Entry>> {
        let result = self.exec(
        "MATCH (e:Entry)<--(x:EntryState)
          WITH distinct e, max(x.created) as max
          MATCH e<--(s:EntryState)
          WHERE s.created = max
          WITH e,s
          MATCH e<-[:BELONGS_TO]-s
          OPTIONAL MATCH (s)<-[:BELONGS_TO]-(c:Category)
          WITH e, s, collect(DISTINCT c.id) as categories
          RETURN {
            id          : e.id,
            created     : s.created,
            version     : s.version,
            title       : s.title,
            description : s.description,
            lat         : s.lat,
            lng         : s.lng,
            street      : s.street,
            zip         : s.zip,
            city        : s.city,
            country     : s.country,
            email       : s.email,
            telephone   : s.telephone,
            homepage    : s.homepage,
            categories  : categories,
            license     : s.license
          } AS e
          ORDER BY e.created DESC")?;
        Ok(result.rows()
            .filter_map(|r| r.get::<Entry>("e").ok())
            .collect::<Vec<Entry>>())
    }

    fn create_entry(&mut self, e: &Entry) -> Result<()> {
        self.exec(cypher_stmt!(
        "MATCH (c:Category)
         WHERE c.id in {categories}
         WITH
            collect(DISTINCT c)    AS cats,
            collect(DISTINCT c.id) AS cat_ids,
            count(c)               AS cnt
         WHERE cnt > 0
         CREATE (e:Entry {id:{id}})
         MERGE e<-[:BELONGS_TO]-(s:EntryState {
           created : timestamp(),
           version : 1
         })
         SET s.title       = {title},
             s.description = {description},
             s.lat         = {lat},
             s.lng         = {lng},
             s.street      = {street},
             s.zip         = {zip},
             s.city        = {city},
             s.country     = {country},
             s.email       = {email},
             s.telephone   = {telephone},
             s.homepage    = {homepage},
             s.license     = {license}
         FOREACH (c IN cats |
           MERGE c-[:BELONGS_TO]->s
         )",
        {
            "id"          => &e.id,
            "title"       => &e.title,
            "description" => &e.description,
            "lat"         => &e.lat,
            "lng"         => &e.lng,
            "street"      => &e.street,
            "zip"         => &e.zip,
            "city"        => &e.city,
            "country"     => &e.country,
            "email"       => &e.email,
            "telephone"   => &e.telephone,
            "homepage"    => &e.homepage,
            "license"     => &e.license,
            "categories"  => &e.categories
        })?)?;
        Ok(())
    }

    fn create_tag(&mut self, t: &Tag) -> Result<()> {
        self.exec(cypher_stmt!("MERGE (t:Tag {id:{id}})",
        { "id" => &t.id })?)?;
        Ok(())
    }

    fn create_user(&mut self, u: &User) -> Result<()> {
        self.exec(cypher_stmt!(
        "MERGE (
           u:User {
             username:{username},
             password:{password},
             email:{email}
           }
        )",
        {
            "username" => &u.username,
            "password" => &u.password,
            "email"    => &u.email
        })?)?;
        Ok(())
    }

    fn create_rating(&mut self, r: &Rating) -> Result<()> {
        self.exec(cypher_stmt!(
        "MERGE (r:Rating {
             id      : {id},
             title   : {title},
             created : {created},
             value   : {value},
             context : {context},
             source  : {source}
        })",
        {
            "id"        => &r.id,
            "title"     => &r.title,
            "created"   => &r.created,
            "value"     => &r.value,
            "context"   => &r.context,
            "source"    => &r.source
        })?)?;
        Ok(())
    }

    fn create_comment(&mut self, c: &Comment) -> Result<()> {
        self.exec(cypher_stmt!(
        "MERGE (
           c:Comment {
             id      : {id},
             created : {created},
             text    : {text}
           }
        )",
        {
            "id"        => &c.id,
            "created"   => &c.created,
            "text"      => &c.text
        })?)?;
        Ok(())
    }

    fn create_triple(&mut self, t: &Triple) -> Result<()> {

        let predicate = neo4j_edge_name(t);
        let (subject_type, subject_id) = object_id_to_neo4j_label(&t.subject);
        let (object_type, object_id) = object_id_to_neo4j_label(&t.object);

        let stmt = format!(
           "MATCH (s:{s_type})
            WHERE s.id = \"{s_id}\"
            WITH s
            MATCH (o:{o_type})
            WHERE o.id = \"{o_id}\"
            WITH s,o
            MERGE (s)-[:{predicate}]->(o)",
                s_type = subject_type,
                s_id = subject_id,
                o_type = object_type,
                o_id = object_id,
                predicate = predicate
            );
        self.exec(stmt)?;
        Ok(())
    }

    fn update_entry(&mut self, e: &Entry) -> Result<()> {
        self.exec(cypher_stmt!(
        "MATCH (e:Entry)<--(s:EntryState) WHERE e.id = {id}
         WITH max(s.version) as v
         MATCH (e:Entry)<--(old:EntryState)
         WHERE e.id = {id} AND old.version = v AND old.version + 1 = {version}
         WITH e
         MATCH (c:Category)
         WHERE c.id in {categories}
         WITH e, collect(DISTINCT c) AS cats, count(c) AS cnt
         WHERE cnt > 0
         MERGE e<-[:BELONGS_TO]-(s:EntryState {
           created : timestamp(),
           version : {version}
         })
         SET s.title       = {title},
             s.description = {description},
             s.lat         = {lat},
             s.lng         = {lng},
             s.street      = {street},
             s.zip         = {zip},
             s.city        = {city},
             s.country     = {country},
             s.email       = {email},
             s.telephone   = {telephone},
             s.homepage    = {homepage},
             s.license     = {license}
         FOREACH (c IN cats |
           MERGE (c)-[:BELONGS_TO]->s
         )",
        {
            "id"          => &e.id,
            "version"     => &e.version,
            "title"       => &e.title,
            "description" => &e.description,
            "lat"         => &e.lat,
            "lng"         => &e.lng,
            "street"      => &e.street,
            "zip"         => &e.zip,
            "city"        => &e.city,
            "country"     => &e.country,
            "email"       => &e.email,
            "telephone"   => &e.telephone,
            "homepage"    => &e.homepage,
            "license"     => &e.license,
            "categories"  => &e.categories
        })?)?;
        Ok(())
    }

    fn all_categories(&self) -> Result<Vec<Category>> {
        let result = self.exec(
        "MATCH (c:Category)<--(s:CategoryState)
         RETURN {
           id      : c.id,
           version : s.version,
           created : s.created,
           name    : s.name
         } AS c")?;
        Ok(result
            .rows()
            .filter_map(|r| r.get::<Category>("c").ok())
            .collect::<Vec<Category>>())
    }

    fn all_triples(&self) -> Result<Vec<Triple>> {
        let result = self.exec(
        "MATCH (s)-[p]->(o)
         WHERE (s.id IS NOT NULL) AND (o.id IS NOT NULL)
         RETURN {
            subject: { id: s.id, labels: labels(s) },
            predicate: type(p),
            object: { id: o.id, labels: labels(o) }
         } AS t")?;
        Ok(result
            .rows()
            .filter_map(|r|{
                match r.get::<Neo4jTriple>("t") {
                    Err(err) => {
                         warn!("{}",err);
                         None
                    }
                    Ok(t) => from_neo_triple(t)
                }
            })
            .collect::<Vec<Triple>>())
    }

    fn all_tags(&self) -> Result<Vec<Tag>> {
        let result = self.exec(
        "MATCH (t:Tag) RETURN t")?;
        Ok(result
            .rows()
            .filter_map(|r| r.get::<Tag>("t").ok())
            .collect::<Vec<Tag>>())
    }

    fn all_ratings(&self) -> Result<Vec<Rating>> {
        let result = self.exec(
        "MATCH (r:Rating) RETURN r")?;
        Ok(result
            .rows()
            .filter_map(|r| r.get::<Rating>("r").ok())
            .collect::<Vec<Rating>>())
    }

    fn all_comments(&self) -> Result<Vec<Comment>> {
        let result = self.exec(
        "MATCH (c:Comment) RETURN c")?;
        Ok(result
            .rows()
            .filter_map(|r| r.get::<Comment>("c").ok())
            .collect::<Vec<Comment>>())
    }

    fn delete_triple(&mut self, t: &Triple) -> Result<()> {
        let predicate = neo4j_edge_name(t);
        let (subject_type, subject_id) = object_id_to_neo4j_label(&t.subject);
        let (object_type, object_id) = object_id_to_neo4j_label(&t.object);
        let stmt = format!(
           "MATCH (s:{s_type})-[p:{predicate}]->(o:{o_type})
            WHERE s.id = \"{s_id}\" AND o.id = \"{o_id}\"
            DELETE p",
                s_type = subject_type,
                s_id = subject_id,
                o_type = object_type,
                o_id = object_id,
                predicate = predicate
            );
        self.exec(stmt)?;
        Ok(())
    }
}
<commit_msg>fix(rating-source): console output for debugging<commit_after>use business::db::Db;
use entities::*;
use rusted_cypher::GraphClient;
use business::error::RepoError;
use std::result;

type Result<T> = result::Result<T, RepoError>;

fn neo4j_edge_name(t: &Triple) -> &str {
    match t.predicate {
       Relation::IsTaggedWith    => "IS_TAGGED_WITH",
       Relation::IsRatedWith     => "IS_RATED_WITH",
       Relation::IsCommentedWith => "IS_COMMENTED_WITH",
       Relation::CreatedBy       => "CREATED_BY"
    }.into()
}

fn object_id_to_neo4j_label(id: &ObjectId) -> (&str,&str) {
    match *id {
        ObjectId::Entry(ref id) => ("Entry",id),
        ObjectId::Tag(ref id) => ("Tag",id),
        ObjectId::User(ref id) => ("User",id),
        ObjectId::Comment(ref id) => ("Comment",id),
        ObjectId::Rating(ref id) => ("Rating",id)
    }
}

fn neo4j_label_to_object_id(label: &str, id: String) -> Option<ObjectId> {
    match label {
        "Entry"     => Some(ObjectId::Entry(id)),
        "Tag"       => Some(ObjectId::Tag(id)),
        "User"      => Some(ObjectId::User(id)),
        "Comment"   => Some(ObjectId::Comment(id)),
        "Rating"    => Some(ObjectId::Rating(id)),
        _           => None,
    }
}

fn neo4j_relation_to_relation(rel: &str) -> Option<Relation> {
    match rel {
        "IS_TAGGED_WITH"    => Some(Relation::IsTaggedWith),
        "IS_RATED_WITH"     => Some(Relation::IsRatedWith),
        "IS_COMMENTED_WITH" => Some(Relation::IsCommentedWith),
        "CREATED_BY"        => Some(Relation::CreatedBy),
        _                   => None
    }
}

#[derive(Deserialize,Debug)]
struct Neo4jObj {
    labels: Vec<String>,
    id: String
}

#[derive(Deserialize,Debug)]
struct Neo4jTriple {
    subject: Neo4jObj,
    predicate: String,
    object: Neo4jObj
}

fn from_neo_triple(t: Neo4jTriple) -> Option<Triple> {
    if t.subject.labels.is_empty() || t.object.labels.is_empty() {
        warn!("No labels found in {:?}", t);
        return None;
    }
    let subject = neo4j_label_to_object_id(&t.subject.labels[0], t.subject.id);
    let predicate = neo4j_relation_to_relation(&t.predicate);
    let object = neo4j_label_to_object_id(&t.object.labels[0], t.object.id);

    if let (Some(s), Some(p), Some(o)) = (subject, predicate, object) {
        Some(Triple {
            subject: s,
            predicate: p,
            object: o
        })
    } else {
        None
    }
}

impl Db for GraphClient {
    fn get_entry(&self, id: &str) -> Result<Entry> {
        let result = self.exec(cypher_stmt!(
        "MATCH (e:Entry)<--(s:EntryState) WHERE e.id = {id}
         WITH max(s.version) as version
         MATCH (e:Entry)<--(s:EntryState)
         WHERE e.id = {id} AND s.version = version
         WITH e, s
         MATCH s<-[:BELONGS_TO]-(c:Category)
         WITH e, s, collect(DISTINCT c.id) as categories
         RETURN {
           id          : e.id,
           created     : s.created,
           version     : s.version,
           title       : s.title,
           description : s.description,
           lat         : s.lat,
           lng         : s.lng,
           street      : s.street,
           zip         : s.zip,
           city        : s.city,
           country     : s.country,
           email       : s.email,
           telephone   : s.telephone,
           homepage    : s.homepage,
           categories  : categories,
           license     : s.license
         } AS e
         ORDER BY e.created DESC", {"id" => &id})?)?;
        let r = result.rows().next().ok_or(RepoError::NotFound)?;
        let e = r.get::<Entry>("e")?;
        Ok(e)
    }

    fn get_user(&self, username: &str) -> Result<User> {
        let result = self.exec(cypher_stmt!(
        "MATCH (u:User)
         WHERE u.username = {username}
         RETURN u",
        { "username" => username })?)?;
        let r = result.rows().next().ok_or(RepoError::NotFound)?;
        let u = r.get::<User>("u")?;
        Ok(u)
    }

    fn all_entries(&self) -> Result<Vec<Entry>> {
        let result = self.exec(
        "MATCH (e:Entry)<--(x:EntryState)
          WITH distinct e, max(x.created) as max
          MATCH e<--(s:EntryState)
          WHERE s.created = max
          WITH e,s
          MATCH e<-[:BELONGS_TO]-s
          OPTIONAL MATCH (s)<-[:BELONGS_TO]-(c:Category)
          WITH e, s, collect(DISTINCT c.id) as categories
          RETURN {
            id          : e.id,
            created     : s.created,
            version     : s.version,
            title       : s.title,
            description : s.description,
            lat         : s.lat,
            lng         : s.lng,
            street      : s.street,
            zip         : s.zip,
            city        : s.city,
            country     : s.country,
            email       : s.email,
            telephone   : s.telephone,
            homepage    : s.homepage,
            categories  : categories,
            license     : s.license
          } AS e
          ORDER BY e.created DESC")?;
        Ok(result.rows()
            .filter_map(|r| r.get::<Entry>("e").ok())
            .collect::<Vec<Entry>>())
    }

    fn create_entry(&mut self, e: &Entry) -> Result<()> {
        self.exec(cypher_stmt!(
        "MATCH (c:Category)
         WHERE c.id in {categories}
         WITH
            collect(DISTINCT c)    AS cats,
            collect(DISTINCT c.id) AS cat_ids,
            count(c)               AS cnt
         WHERE cnt > 0
         CREATE (e:Entry {id:{id}})
         MERGE e<-[:BELONGS_TO]-(s:EntryState {
           created : timestamp(),
           version : 1
         })
         SET s.title       = {title},
             s.description = {description},
             s.lat         = {lat},
             s.lng         = {lng},
             s.street      = {street},
             s.zip         = {zip},
             s.city        = {city},
             s.country     = {country},
             s.email       = {email},
             s.telephone   = {telephone},
             s.homepage    = {homepage},
             s.license     = {license}
         FOREACH (c IN cats |
           MERGE c-[:BELONGS_TO]->s
         )",
        {
            "id"          => &e.id,
            "title"       => &e.title,
            "description" => &e.description,
            "lat"         => &e.lat,
            "lng"         => &e.lng,
            "street"      => &e.street,
            "zip"         => &e.zip,
            "city"        => &e.city,
            "country"     => &e.country,
            "email"       => &e.email,
            "telephone"   => &e.telephone,
            "homepage"    => &e.homepage,
            "license"     => &e.license,
            "categories"  => &e.categories
        })?)?;
        Ok(())
    }

    fn create_tag(&mut self, t: &Tag) -> Result<()> {
        self.exec(cypher_stmt!("MERGE (t:Tag {id:{id}})",
        { "id" => &t.id })?)?;
        Ok(())
    }

    fn create_user(&mut self, u: &User) -> Result<()> {
        self.exec(cypher_stmt!(
        "MERGE (
           u:User {
             username:{username},
             password:{password},
             email:{email}
           }
        )",
        {
            "username" => &u.username,
            "password" => &u.password,
            "email"    => &u.email
        })?)?;
        Ok(())
    }

    fn create_rating(&mut self, r: &Rating) -> Result<()> {
        let s = r.source.clone();
        println!("source: {}", s.unwrap_or("no source".into()));
        self.exec(cypher_stmt!(
        "MERGE (r:Rating {
             id      : {id},
             title   : {title},
             created : {created},
             value   : {value},
             context : {context},
             source  : {source}
        })",
        {
            "id"        => &r.id,
            "title"     => &r.title,
            "created"   => &r.created,
            "value"     => &r.value,
            "context"   => &r.context,
            "source"    => &r.source
        })?)?;
        println!("Ok");
        Ok(())
    }

    fn create_comment(&mut self, c: &Comment) -> Result<()> {
        self.exec(cypher_stmt!(
        "MERGE (
           c:Comment {
             id      : {id},
             created : {created},
             text    : {text}
           }
        )",
        {
            "id"        => &c.id,
            "created"   => &c.created,
            "text"      => &c.text
        })?)?;
        Ok(())
    }

    fn create_triple(&mut self, t: &Triple) -> Result<()> {

        let predicate = neo4j_edge_name(t);
        let (subject_type, subject_id) = object_id_to_neo4j_label(&t.subject);
        let (object_type, object_id) = object_id_to_neo4j_label(&t.object);

        let stmt = format!(
           "MATCH (s:{s_type})
            WHERE s.id = \"{s_id}\"
            WITH s
            MATCH (o:{o_type})
            WHERE o.id = \"{o_id}\"
            WITH s,o
            MERGE (s)-[:{predicate}]->(o)",
                s_type = subject_type,
                s_id = subject_id,
                o_type = object_type,
                o_id = object_id,
                predicate = predicate
            );
        self.exec(stmt)?;
        Ok(())
    }

    fn update_entry(&mut self, e: &Entry) -> Result<()> {
        self.exec(cypher_stmt!(
        "MATCH (e:Entry)<--(s:EntryState) WHERE e.id = {id}
         WITH max(s.version) as v
         MATCH (e:Entry)<--(old:EntryState)
         WHERE e.id = {id} AND old.version = v AND old.version + 1 = {version}
         WITH e
         MATCH (c:Category)
         WHERE c.id in {categories}
         WITH e, collect(DISTINCT c) AS cats, count(c) AS cnt
         WHERE cnt > 0
         MERGE e<-[:BELONGS_TO]-(s:EntryState {
           created : timestamp(),
           version : {version}
         })
         SET s.title       = {title},
             s.description = {description},
             s.lat         = {lat},
             s.lng         = {lng},
             s.street      = {street},
             s.zip         = {zip},
             s.city        = {city},
             s.country     = {country},
             s.email       = {email},
             s.telephone   = {telephone},
             s.homepage    = {homepage},
             s.license     = {license}
         FOREACH (c IN cats |
           MERGE (c)-[:BELONGS_TO]->s
         )",
        {
            "id"          => &e.id,
            "version"     => &e.version,
            "title"       => &e.title,
            "description" => &e.description,
            "lat"         => &e.lat,
            "lng"         => &e.lng,
            "street"      => &e.street,
            "zip"         => &e.zip,
            "city"        => &e.city,
            "country"     => &e.country,
            "email"       => &e.email,
            "telephone"   => &e.telephone,
            "homepage"    => &e.homepage,
            "license"     => &e.license,
            "categories"  => &e.categories
        })?)?;
        Ok(())
    }

    fn all_categories(&self) -> Result<Vec<Category>> {
        let result = self.exec(
        "MATCH (c:Category)<--(s:CategoryState)
         RETURN {
           id      : c.id,
           version : s.version,
           created : s.created,
           name    : s.name
         } AS c")?;
        Ok(result
            .rows()
            .filter_map(|r| r.get::<Category>("c").ok())
            .collect::<Vec<Category>>())
    }

    fn all_triples(&self) -> Result<Vec<Triple>> {
        let result = self.exec(
        "MATCH (s)-[p]->(o)
         WHERE (s.id IS NOT NULL) AND (o.id IS NOT NULL)
         RETURN {
            subject: { id: s.id, labels: labels(s) },
            predicate: type(p),
            object: { id: o.id, labels: labels(o) }
         } AS t")?;
        Ok(result
            .rows()
            .filter_map(|r|{
                match r.get::<Neo4jTriple>("t") {
                    Err(err) => {
                         warn!("{}",err);
                         None
                    }
                    Ok(t) => from_neo_triple(t)
                }
            })
            .collect::<Vec<Triple>>())
    }

    fn all_tags(&self) -> Result<Vec<Tag>> {
        let result = self.exec(
        "MATCH (t:Tag) RETURN t")?;
        Ok(result
            .rows()
            .filter_map(|r| r.get::<Tag>("t").ok())
            .collect::<Vec<Tag>>())
    }

    fn all_ratings(&self) -> Result<Vec<Rating>> {
        let result = self.exec(
        "MATCH (r:Rating) RETURN r")?;
        Ok(result
            .rows()
            .filter_map(|r| r.get::<Rating>("r").ok())
            .collect::<Vec<Rating>>())
    }

    fn all_comments(&self) -> Result<Vec<Comment>> {
        let result = self.exec(
        "MATCH (c:Comment) RETURN c")?;
        Ok(result
            .rows()
            .filter_map(|r| r.get::<Comment>("c").ok())
            .collect::<Vec<Comment>>())
    }

    fn delete_triple(&mut self, t: &Triple) -> Result<()> {
        let predicate = neo4j_edge_name(t);
        let (subject_type, subject_id) = object_id_to_neo4j_label(&t.subject);
        let (object_type, object_id) = object_id_to_neo4j_label(&t.object);
        let stmt = format!(
           "MATCH (s:{s_type})-[p:{predicate}]->(o:{o_type})
            WHERE s.id = \"{s_id}\" AND o.id = \"{o_id}\"
            DELETE p",
                s_type = subject_type,
                s_id = subject_id,
                o_type = object_type,
                o_id = object_id,
                predicate = predicate
            );
        self.exec(stmt)?;
        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Awesome compatibility modules

#![cfg_attr(test, deny(bad_style,
       const_err,
       dead_code,
       improper_ctypes,
       legacy_directory_ownership,
       non_shorthand_field_patterns,
       no_mangle_generic_items,
       overflowing_literals,
       path_statements ,
       patterns_in_fns_without_body,
       plugin_as_library,
       private_in_public,
       private_no_mangle_fns,
       private_no_mangle_statics,
       safe_extern_statics,
       unconditional_recursion,
       unions_with_drop_fields,
       unused,
       unused_allocation,
       unused_comparisons,
       unused_parens,
       while_true))]

// Allowed by default
#![cfg_attr(test, deny(missing_docs,
       trivial_numeric_casts,
       unused_extern_crates,
       unused_import_braces,
       unused_qualifications))]

#[macro_use]
extern crate bitflags;
extern crate cairo;
extern crate cairo_sys;
extern crate env_logger;
extern crate exec;
extern crate getopts;
extern crate gdk_pixbuf;
extern crate glib;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate nix;
extern crate libc;
extern crate rlua;
extern crate tempfile;
extern crate xcb;
#[macro_use]
extern crate wayland_client;
extern crate wayland_sys;

// TODO remove
extern crate wlroots;

#[macro_use]
mod macros;
mod objects;
mod common;
mod wayland_obj;
mod awesome;
mod keygrabber;
mod mousegrabber;
mod root;
mod lua;
mod wayland_protocols;

use std::{env, mem, path::PathBuf, process::exit, io::{self, Write}};

use exec::Command;
use rlua::{LightUserData, Lua, Table};
use log::Level;
use nix::sys::signal::{self, SaFlags, SigAction, SigHandler, SigSet};
use xcb::{xkb, Connection};
use wayland_client::{Display, GlobalManager, EventQueue, GlobalError, ConnectError};
use wayland_client::protocol::{wl_compositor, wl_shm, wl_output, wl_display::RequestsTrait};
use wayland_client::sys::client::wl_display;

use self::lua::{LUA, NEXT_LUA};
use wayland_protocols::xdg_shell::xdg_wm_base;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const GIT_VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/git-version.txt"));
pub const GLOBAL_SIGNALS: &'static str = "__awesome_global_signals";
pub const XCB_CONNECTION_HANDLE: &'static str = "__xcb_connection";

/// The state passed into C to store it during the glib loop.
///
/// It's passed back to us when Awesome needs a refresh so we can
/// construct any Wayland objects.
#[repr(C)]
struct WaylandState {
    pub display: Display,
    pub event_queue: EventQueue
}

/// Called from `wayland_glib_interface.c` after every call back into the
/// wayland event loop.
///
/// This restarts the Lua thread if there is a new one pending
#[no_mangle]
pub extern "C" fn awesome_refresh(wayland_state: *mut libc::c_void) {
    // NOTE
    // This is safe because it's way back up the stack where we can't access it.
    //
    // The moment that stack is accessible this pointer will be lost.
    //
    // The only way it's unsafe is if we destructure `WaylandState`,
    // which we can't do because it's borrowed.
    let _wayland_state = unsafe { &mut *(wayland_state as *mut WaylandState) };
    NEXT_LUA.with(|new_lua_check| {
        if new_lua_check.get() {
            new_lua_check.set(false);
            let awesome = env::args().next().unwrap();
            let args: Vec<_> = env::args().skip(1).collect();
            let err = Command::new(awesome)
                .args(args.as_slice())
                .exec();
            error!("error: {:?}", err);
            panic!("Could not restart Awesome");
        }
    });
}

fn main() {
    let mut opts = getopts::Options::new();
    let matches = match opts.optflag("", "version", "show version information")
                            .parse(env::args().skip(1)) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("{}", f.to_string());
            exit(1);
        }
    };
    if matches.opt_present("version") {
        if !GIT_VERSION.is_empty() {
            println!("Way Cooler {} @ {}", VERSION, GIT_VERSION);
        } else {
            println!("Way Cooler {}", VERSION);
        }
        return
    }
    init_logs();
    let sig_action = SigAction::new(SigHandler::Handler(sig_handle),
                                    SaFlags::empty(),
                                    SigSet::empty());
    unsafe {
        signal::sigaction(signal::SIGINT, &sig_action)
            .expect("Could not set SIGINT catcher");
    }
    lua::init_awesome_libraries();
    init_wayland();
    lua::run_awesome();
}

fn init_wayland() {
    let (display, mut event_queue) = match Display::connect_to_env() {
        Ok(res) => res,
        Err(err) => {
            match err {
                ConnectError::NoWaylandLib =>
                    error!("Could not find Wayland library, is it installed and in PATH?"),
                ConnectError::NoCompositorListening => {
                    error!("Could not connect to Wayland server. Is it running?");
                    error!("WAYLAND_DISPLAY={}", env::var("WAYLAND_DISPLAY")
                           .unwrap_or_else(|_| "".into()));
                },
                ConnectError::InvalidName =>
                    error!("Invalid socket name provided")
            }
            exit(1);
        }
    };
    let globals = GlobalManager::new_with_cb(
        display.get_registry().unwrap(),
        global_filter!(
            [
                wl_output::WlOutput,
                wayland_obj::WL_OUTPUT_VERSION,
                wayland_obj::Output::new
            ],
            [
                wl_compositor::WlCompositor,
                wayland_obj::WL_COMPOSITOR_VERSION,
                wayland_obj::wl_compositor_init
            ],
            [
                wl_shm::WlShm,
                wayland_obj::WL_SHM_VERSION,
                wayland_obj::wl_shm_init
            ]
        ),
    );
    event_queue.sync_roundtrip().unwrap();
    let xwm_base_proxy = match globals.instantiate_exact::
    <xdg_wm_base::XdgWmBase>(wayland_obj::XDG_WM_BASE_VERSION) {
        Err(GlobalError::Missing) => {
            error!("Missing xdg_wm_base global (version {})",
                   wayland_obj::XDG_WM_BASE_VERSION);
            error!("Your compositor doesn't support the xdg shell protocol");
            error!("This protocol is necessary for Awesome to function");
            exit(1);
        },
        Err(GlobalError::VersionTooLow(version)) => {
            error!("Got xdg_wm_base version {}, expected version {}",
                   version, wayland_obj::XDG_WM_BASE_VERSION);
            error!("Your compositor doesn't support version {} \
                    of the xdg shell protocol", wayland_obj::XDG_WM_BASE_VERSION);
            error!("Ensure your compositor is up to date");
            exit(1);
        },
        Ok(proxy) => Ok(proxy)
    };
    wayland_obj::xdg_shell_init(xwm_base_proxy, ());
    event_queue.sync_roundtrip().unwrap();
    let mut wayland_state = WaylandState { display, event_queue };
    let display_ptr = wayland_state.display.c_ptr() as *mut wl_display;
    unsafe {
        #[link(name = "wayland_glib_interface", kind = "static")]
        extern "C" {
            fn wayland_glib_interface_init(display: *mut wl_display,
                                           wayland_state: *mut libc::c_void);
        }
        wayland_glib_interface_init(display_ptr,
                                    &mut wayland_state as *mut _ as _);
        ::std::mem::forget(wayland_state);
        ::std::mem::forget(globals);
    }
}

fn setup_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;

    for mut xdg_data_path in
        env::var("XDG_DATA_DIRS").unwrap_or("/usr/local/share:/usr/share".into())
                                 .split(':')
                                 .map(PathBuf::from)
    {
        xdg_data_path.push("awesome/lib");
        path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                               xdg_data_path.as_os_str().to_string_lossy()));
        cpath.push_str(&format!(";{}/?.so", xdg_data_path.into_os_string().to_string_lossy()));
    }

    for mut xdg_config_path in env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into())
                                                          .split(':')
                                                          .map(PathBuf::from)
    {
        xdg_config_path.push("awesome");
        cpath.push_str(&format!(";{}/?.so",
                                xdg_config_path.into_os_string().to_string_lossy()));
    }

    package.set("path", path)?;
    package.set("cpath", cpath)?;

    Ok(())
}

/// Set up global signals value
///
/// We need to store this in Lua, because this make it safer to use.
fn setup_global_signals(lua: &Lua) -> rlua::Result<()> {
    lua.set_named_registry_value(GLOBAL_SIGNALS, lua.create_table()?)
}

/// Sets up the xcb connection and stores it in Lua (for us to access it later)
fn setup_xcb_connection(lua: &Lua) -> rlua::Result<()> {
    let con = match Connection::connect(None) {
        Err(err) => {
            error!("Way Cooler requires XWayland in order to function");
            error!("However, xcb could not connect to it. Is it running?");
            error!("{:?}", err);
            panic!("Could not connect to XWayland instance");
        }
        Ok(con) => con.0
    };
    // Tell xcb we are using the xkb extension
    match xkb::use_extension(&con, 1, 0).get_reply() {
        Ok(r) => {
            if !r.supported() {
                panic!("xkb-1.0 is not supported");
            }
        }
        Err(err) => {
            panic!("Could not get xkb extension supported version {:?}", err);
        }
    }
    lua.set_named_registry_value(XCB_CONNECTION_HANDLE,
                                  LightUserData(con.get_raw_conn() as _))?;
    mem::forget(con);
    Ok(())
}

/// Formats the log strings properly
fn log_format(buf: &mut env_logger::fmt::Formatter, record: &log::Record) -> Result<(), io::Error> {
    let color = match record.level() {
        Level::Info => "",
        Level::Trace => "\x1B[37m",
        Level::Debug => "\x1B[44m",
        Level::Warn => "\x1B[33m",
        Level::Error => "\x1B[31m"
    };
    let mut module_path = record.module_path().unwrap_or("?");
    if let Some(index) = module_path.find("way_cooler::") {
        let index = index + "way_cooler::".len();
        module_path = &module_path[index..];
    }
    writeln!(buf, "{} {} [{}] \x1B[37m{}:{}\x1B[0m{0} {} \x1B[0m",
            color,
            record.level(),
            module_path,
            record.file().unwrap_or("?"),
            record.line().unwrap_or(0),
            record.args())
}

fn init_logs() {
    let env = env_logger::Env::default()
        .filter_or("WAY_COOLER_LOG", "trace");
    env_logger::Builder::from_env(env)
        .format(log_format)
        .init();
    info!("Logger initialized");
}

/// Handler for SIGINT signal
extern "C" fn sig_handle(_: nix::libc::c_int) {
    lua::terminate();
    exit(130);
}
<commit_msg>Moved glib init to own function<commit_after>//! Awesome compatibility modules

#![cfg_attr(test, deny(bad_style,
       const_err,
       dead_code,
       improper_ctypes,
       legacy_directory_ownership,
       non_shorthand_field_patterns,
       no_mangle_generic_items,
       overflowing_literals,
       path_statements ,
       patterns_in_fns_without_body,
       plugin_as_library,
       private_in_public,
       private_no_mangle_fns,
       private_no_mangle_statics,
       safe_extern_statics,
       unconditional_recursion,
       unions_with_drop_fields,
       unused,
       unused_allocation,
       unused_comparisons,
       unused_parens,
       while_true))]

// Allowed by default
#![cfg_attr(test, deny(missing_docs,
       trivial_numeric_casts,
       unused_extern_crates,
       unused_import_braces,
       unused_qualifications))]

#[macro_use]
extern crate bitflags;
extern crate cairo;
extern crate cairo_sys;
extern crate env_logger;
extern crate exec;
extern crate getopts;
extern crate gdk_pixbuf;
extern crate glib;
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
extern crate nix;
extern crate libc;
extern crate rlua;
extern crate tempfile;
extern crate xcb;
#[macro_use]
extern crate wayland_client;
extern crate wayland_sys;

// TODO remove
extern crate wlroots;

#[macro_use]
mod macros;
mod objects;
mod common;
mod wayland_obj;
mod awesome;
mod keygrabber;
mod mousegrabber;
mod root;
mod lua;
mod wayland_protocols;

use std::{env, mem, path::PathBuf, process::exit, io::{self, Write}};

use exec::Command;
use rlua::{LightUserData, Lua, Table};
use log::Level;
use nix::sys::signal::{self, SaFlags, SigAction, SigHandler, SigSet};
use xcb::{xkb, Connection};
use wayland_client::{Display, GlobalManager, EventQueue, GlobalError, ConnectError};
use wayland_client::protocol::{wl_compositor, wl_shm, wl_output, wl_display::RequestsTrait};
use wayland_client::sys::client::wl_display;

use self::lua::{LUA, NEXT_LUA};
use wayland_protocols::xdg_shell::xdg_wm_base;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");
const GIT_VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/git-version.txt"));
pub const GLOBAL_SIGNALS: &'static str = "__awesome_global_signals";
pub const XCB_CONNECTION_HANDLE: &'static str = "__xcb_connection";

/// The state passed into C to store it during the glib loop.
///
/// It's passed back to us when Awesome needs a refresh so we can
/// construct any Wayland objects.
#[repr(C)]
struct WaylandState {
    pub display: Display,
    pub event_queue: EventQueue
}

/// Called from `wayland_glib_interface.c` after every call back into the
/// wayland event loop.
///
/// This restarts the Lua thread if there is a new one pending
#[no_mangle]
pub extern "C" fn awesome_refresh(wayland_state: *mut libc::c_void) {
    // NOTE
    // This is safe because it's way back up the stack where we can't access it.
    //
    // The moment that stack is accessible this pointer will be lost.
    //
    // The only way it's unsafe is if we destructure `WaylandState`,
    // which we can't do because it's borrowed.
    let _wayland_state = unsafe { &mut *(wayland_state as *mut WaylandState) };
    NEXT_LUA.with(|new_lua_check| {
        if new_lua_check.get() {
            new_lua_check.set(false);
            let awesome = env::args().next().unwrap();
            let args: Vec<_> = env::args().skip(1).collect();
            let err = Command::new(awesome)
                .args(args.as_slice())
                .exec();
            error!("error: {:?}", err);
            panic!("Could not restart Awesome");
        }
    });
}

fn main() {
    let mut opts = getopts::Options::new();
    let matches = match opts.optflag("", "version", "show version information")
                            .parse(env::args().skip(1)) {
        Ok(m) => m,
        Err(f) => {
            eprintln!("{}", f.to_string());
            exit(1);
        }
    };
    if matches.opt_present("version") {
        if !GIT_VERSION.is_empty() {
            println!("Way Cooler {} @ {}", VERSION, GIT_VERSION);
        } else {
            println!("Way Cooler {}", VERSION);
        }
        return
    }
    init_logs();
    let sig_action = SigAction::new(SigHandler::Handler(sig_handle),
                                    SaFlags::empty(),
                                    SigSet::empty());
    unsafe {
        signal::sigaction(signal::SIGINT, &sig_action)
            .expect("Could not set SIGINT catcher");
    }
    lua::init_awesome_libraries();
    let (display, event_queue, _globals) = init_wayland();
    init_glib(display, event_queue);
    lua::run_awesome();
}

fn init_wayland() -> (Display, EventQueue, GlobalManager) {
    let (display, mut event_queue) = match Display::connect_to_env() {
        Ok(res) => res,
        Err(err) => {
            match err {
                ConnectError::NoWaylandLib =>
                    error!("Could not find Wayland library, is it installed and in PATH?"),
                ConnectError::NoCompositorListening => {
                    error!("Could not connect to Wayland server. Is it running?");
                    error!("WAYLAND_DISPLAY={}", env::var("WAYLAND_DISPLAY")
                           .unwrap_or_else(|_| "".into()));
                },
                ConnectError::InvalidName =>
                    error!("Invalid socket name provided")
            }
            exit(1);
        }
    };
    let globals = GlobalManager::new_with_cb(
        display.get_registry().unwrap(),
        global_filter!(
            [
                wl_output::WlOutput,
                wayland_obj::WL_OUTPUT_VERSION,
                wayland_obj::Output::new
            ],
            [
                wl_compositor::WlCompositor,
                wayland_obj::WL_COMPOSITOR_VERSION,
                wayland_obj::wl_compositor_init
            ],
            [
                wl_shm::WlShm,
                wayland_obj::WL_SHM_VERSION,
                wayland_obj::wl_shm_init
            ]
        ),
    );
    event_queue.sync_roundtrip().unwrap();
    let xwm_base_proxy = match globals.instantiate_exact::
    <xdg_wm_base::XdgWmBase>(wayland_obj::XDG_WM_BASE_VERSION) {
        Err(GlobalError::Missing) => {
            error!("Missing xdg_wm_base global (version {})",
                   wayland_obj::XDG_WM_BASE_VERSION);
            error!("Your compositor doesn't support the xdg shell protocol");
            error!("This protocol is necessary for Awesome to function");
            exit(1);
        },
        Err(GlobalError::VersionTooLow(version)) => {
            error!("Got xdg_wm_base version {}, expected version {}",
                   version, wayland_obj::XDG_WM_BASE_VERSION);
            error!("Your compositor doesn't support version {} \
                    of the xdg shell protocol", wayland_obj::XDG_WM_BASE_VERSION);
            error!("Ensure your compositor is up to date");
            exit(1);
        },
        Ok(proxy) => Ok(proxy)
    };
    wayland_obj::xdg_shell_init(xwm_base_proxy, ());
    event_queue.sync_roundtrip().unwrap();
    (display, event_queue, globals)
}

/// Init the glib main loop.
fn init_glib(display: Display, event_queue: EventQueue) {
    let mut wayland_state = WaylandState { display, event_queue };
    let display_ptr = wayland_state.display.c_ptr() as *mut wl_display;
    unsafe {
        #[link(name = "wayland_glib_interface", kind = "static")]
        extern "C" {
            fn wayland_glib_interface_init(display: *mut wl_display,
                                           wayland_state: *mut libc::c_void);
        }
        wayland_glib_interface_init(display_ptr,
                                    &mut wayland_state as *mut _ as _);
        ::std::mem::forget(wayland_state);
    }
}

fn setup_awesome_path(lua: &Lua) -> rlua::Result<()> {
    let globals = lua.globals();
    let package: Table = globals.get("package")?;
    let mut path = package.get::<_, String>("path")?;
    let mut cpath = package.get::<_, String>("cpath")?;

    for mut xdg_data_path in
        env::var("XDG_DATA_DIRS").unwrap_or("/usr/local/share:/usr/share".into())
                                 .split(':')
                                 .map(PathBuf::from)
    {
        xdg_data_path.push("awesome/lib");
        path.push_str(&format!(";{0}/?.lua;{0}/?/init.lua",
                               xdg_data_path.as_os_str().to_string_lossy()));
        cpath.push_str(&format!(";{}/?.so", xdg_data_path.into_os_string().to_string_lossy()));
    }

    for mut xdg_config_path in env::var("XDG_CONFIG_DIRS").unwrap_or("/etc/xdg".into())
                                                          .split(':')
                                                          .map(PathBuf::from)
    {
        xdg_config_path.push("awesome");
        cpath.push_str(&format!(";{}/?.so",
                                xdg_config_path.into_os_string().to_string_lossy()));
    }

    package.set("path", path)?;
    package.set("cpath", cpath)?;

    Ok(())
}

/// Set up global signals value
///
/// We need to store this in Lua, because this make it safer to use.
fn setup_global_signals(lua: &Lua) -> rlua::Result<()> {
    lua.set_named_registry_value(GLOBAL_SIGNALS, lua.create_table()?)
}

/// Sets up the xcb connection and stores it in Lua (for us to access it later)
fn setup_xcb_connection(lua: &Lua) -> rlua::Result<()> {
    let con = match Connection::connect(None) {
        Err(err) => {
            error!("Way Cooler requires XWayland in order to function");
            error!("However, xcb could not connect to it. Is it running?");
            error!("{:?}", err);
            panic!("Could not connect to XWayland instance");
        }
        Ok(con) => con.0
    };
    // Tell xcb we are using the xkb extension
    match xkb::use_extension(&con, 1, 0).get_reply() {
        Ok(r) => {
            if !r.supported() {
                panic!("xkb-1.0 is not supported");
            }
        }
        Err(err) => {
            panic!("Could not get xkb extension supported version {:?}", err);
        }
    }
    lua.set_named_registry_value(XCB_CONNECTION_HANDLE,
                                  LightUserData(con.get_raw_conn() as _))?;
    mem::forget(con);
    Ok(())
}

/// Formats the log strings properly
fn log_format(buf: &mut env_logger::fmt::Formatter, record: &log::Record) -> Result<(), io::Error> {
    let color = match record.level() {
        Level::Info => "",
        Level::Trace => "\x1B[37m",
        Level::Debug => "\x1B[44m",
        Level::Warn => "\x1B[33m",
        Level::Error => "\x1B[31m"
    };
    let mut module_path = record.module_path().unwrap_or("?");
    if let Some(index) = module_path.find("way_cooler::") {
        let index = index + "way_cooler::".len();
        module_path = &module_path[index..];
    }
    writeln!(buf, "{} {} [{}] \x1B[37m{}:{}\x1B[0m{0} {} \x1B[0m",
            color,
            record.level(),
            module_path,
            record.file().unwrap_or("?"),
            record.line().unwrap_or(0),
            record.args())
}

fn init_logs() {
    let env = env_logger::Env::default()
        .filter_or("WAY_COOLER_LOG", "trace");
    env_logger::Builder::from_env(env)
        .format(log_format)
        .init();
    info!("Logger initialized");
}

/// Handler for SIGINT signal
extern "C" fn sig_handle(_: nix::libc::c_int) {
    lua::terminate();
    exit(130);
}
<|endoftext|>


<commit_before>//! Provides a way to attach fixes to the diagnostics.
//! The same module also has all curret custom fixes for the diagnostics implemented.
use hir::{
    db::AstDatabase,
    diagnostics::{
        Diagnostic, IncorrectCase, MissingFields, MissingOkInTailExpr, NoSuchField,
        UnresolvedModule,
    },
    HasSource, HirDisplay, Semantics, VariantDef,
};
use ide_db::base_db::{AnchoredPathBuf, FileId};
use ide_db::{
    source_change::{FileSystemEdit, SourceFileEdit},
    RootDatabase,
};
use syntax::{
    algo,
    ast::{self, edit::IndentLevel, make},
    AstNode,
};
use text_edit::TextEdit;

use crate::{diagnostics::Fix, references::rename::rename_with_semantics, FilePosition};

/// A [Diagnostic] that potentially has a fix available.
///
/// [Diagnostic]: hir::diagnostics::Diagnostic
pub(crate) trait DiagnosticWithFix: Diagnostic {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix>;
}

impl DiagnosticWithFix for UnresolvedModule {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let unresolved_module = self.decl.to_node(&root);
        Some(Fix::new(
            "Create module",
            FileSystemEdit::CreateFile {
                dst: AnchoredPathBuf {
                    anchor: self.file.original_file(sema.db),
                    path: self.candidate.clone(),
                },
            }
            .into(),
            unresolved_module.syntax().text_range(),
        ))
    }
}

impl DiagnosticWithFix for NoSuchField {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        missing_record_expr_field_fix(
            &sema,
            self.file.original_file(sema.db),
            &self.field.to_node(&root),
        )
    }
}

impl DiagnosticWithFix for MissingFields {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        // Note that although we could add a diagnostics to
        // fill the missing tuple field, e.g :
        // `struct A(usize);`
        // `let a = A { 0: () }`
        // but it is uncommon usage and it should not be encouraged.
        if self.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
            return None;
        }

        let root = sema.db.parse_or_expand(self.file)?;
        let field_list_parent = self.field_list_parent.to_node(&root);
        let old_field_list = field_list_parent.record_expr_field_list()?;
        let mut new_field_list = old_field_list.clone();
        for f in self.missed_fields.iter() {
            let field =
                make::record_expr_field(make::name_ref(&f.to_string()), Some(make::expr_unit()));
            new_field_list = new_field_list.append_field(&field);
        }

        let edit = {
            let mut builder = TextEdit::builder();
            algo::diff(&old_field_list.syntax(), &new_field_list.syntax())
                .into_text_edit(&mut builder);
            builder.finish()
        };
        Some(Fix::new(
            "Fill struct fields",
            SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into(),
            sema.original_range(&field_list_parent.syntax()).range,
        ))
    }
}

impl DiagnosticWithFix for MissingOkInTailExpr {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let tail_expr = self.expr.to_node(&root);
        let tail_expr_range = tail_expr.syntax().text_range();
        let edit = TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax()));
        let source_change =
            SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into();
        Some(Fix::new("Wrap with ok", source_change, tail_expr_range))
    }
}

impl DiagnosticWithFix for IncorrectCase {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let name_node = self.ident.to_node(&root);

        let file_id = self.file.original_file(sema.db);
        let offset = name_node.syntax().text_range().start();
        let file_position = FilePosition { file_id, offset };

        let rename_changes =
            rename_with_semantics(sema, file_position, &self.suggested_text).ok()?;

        let label = format!("Rename to {}", self.suggested_text);
        Some(Fix::new(&label, rename_changes.info, rename_changes.range))
    }
}

fn missing_record_expr_field_fix(
    sema: &Semantics<RootDatabase>,
    usage_file_id: FileId,
    record_expr_field: &ast::RecordExprField,
) -> Option<Fix> {
    let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?;
    let def_id = sema.resolve_variant(record_lit)?;
    let module;
    let def_file_id;
    let record_fields = match VariantDef::from(def_id) {
        VariantDef::Struct(s) => {
            module = s.module(sema.db);
            let source = s.source(sema.db);
            def_file_id = source.file_id;
            let fields = source.value.field_list()?;
            record_field_list(fields)?
        }
        VariantDef::Union(u) => {
            module = u.module(sema.db);
            let source = u.source(sema.db);
            def_file_id = source.file_id;
            source.value.record_field_list()?
        }
        VariantDef::EnumVariant(e) => {
            module = e.module(sema.db);
            let source = e.source(sema.db);
            def_file_id = source.file_id;
            let fields = source.value.field_list()?;
            record_field_list(fields)?
        }
    };
    let def_file_id = def_file_id.original_file(sema.db);

    let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?;
    if new_field_type.is_unknown() {
        return None;
    }
    let new_field = make::record_field(
        None,
        make::name(record_expr_field.field_name()?.text()),
        make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
    );

    let last_field = record_fields.fields().last()?;
    let last_field_syntax = last_field.syntax();
    let indent = IndentLevel::from_node(last_field_syntax);

    let mut new_field = new_field.to_string();
    if usage_file_id != def_file_id {
        new_field = format!("pub(crate) {}", new_field);
    }
    new_field = format!("\n{}{}", indent, new_field);

    let needs_comma = !last_field_syntax.to_string().ends_with(',');
    if needs_comma {
        new_field = format!(",{}", new_field);
    }

    let source_change = SourceFileEdit {
        file_id: def_file_id,
        edit: TextEdit::insert(last_field_syntax.text_range().end(), new_field),
    };
    return Some(Fix::new(
        "Create field",
        source_change.into(),
        record_expr_field.syntax().text_range(),
    ));

    fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> {
        match field_def_list {
            ast::FieldList::RecordFieldList(it) => Some(it),
            ast::FieldList::TupleFieldList(_) => None,
        }
    }
}
<commit_msg>Fix FileId computation in IncorrectCase fix<commit_after>//! Provides a way to attach fixes to the diagnostics.
//! The same module also has all curret custom fixes for the diagnostics implemented.
use hir::{
    db::AstDatabase,
    diagnostics::{
        Diagnostic, IncorrectCase, MissingFields, MissingOkInTailExpr, NoSuchField,
        UnresolvedModule,
    },
    HasSource, HirDisplay, InFile, Semantics, VariantDef,
};
use ide_db::base_db::{AnchoredPathBuf, FileId};
use ide_db::{
    source_change::{FileSystemEdit, SourceFileEdit},
    RootDatabase,
};
use syntax::{
    algo,
    ast::{self, edit::IndentLevel, make},
    AstNode,
};
use text_edit::TextEdit;

use crate::{diagnostics::Fix, references::rename::rename_with_semantics, FilePosition};

/// A [Diagnostic] that potentially has a fix available.
///
/// [Diagnostic]: hir::diagnostics::Diagnostic
pub(crate) trait DiagnosticWithFix: Diagnostic {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix>;
}

impl DiagnosticWithFix for UnresolvedModule {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let unresolved_module = self.decl.to_node(&root);
        Some(Fix::new(
            "Create module",
            FileSystemEdit::CreateFile {
                dst: AnchoredPathBuf {
                    anchor: self.file.original_file(sema.db),
                    path: self.candidate.clone(),
                },
            }
            .into(),
            unresolved_module.syntax().text_range(),
        ))
    }
}

impl DiagnosticWithFix for NoSuchField {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        missing_record_expr_field_fix(
            &sema,
            self.file.original_file(sema.db),
            &self.field.to_node(&root),
        )
    }
}

impl DiagnosticWithFix for MissingFields {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        // Note that although we could add a diagnostics to
        // fill the missing tuple field, e.g :
        // `struct A(usize);`
        // `let a = A { 0: () }`
        // but it is uncommon usage and it should not be encouraged.
        if self.missed_fields.iter().any(|it| it.as_tuple_index().is_some()) {
            return None;
        }

        let root = sema.db.parse_or_expand(self.file)?;
        let field_list_parent = self.field_list_parent.to_node(&root);
        let old_field_list = field_list_parent.record_expr_field_list()?;
        let mut new_field_list = old_field_list.clone();
        for f in self.missed_fields.iter() {
            let field =
                make::record_expr_field(make::name_ref(&f.to_string()), Some(make::expr_unit()));
            new_field_list = new_field_list.append_field(&field);
        }

        let edit = {
            let mut builder = TextEdit::builder();
            algo::diff(&old_field_list.syntax(), &new_field_list.syntax())
                .into_text_edit(&mut builder);
            builder.finish()
        };
        Some(Fix::new(
            "Fill struct fields",
            SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into(),
            sema.original_range(&field_list_parent.syntax()).range,
        ))
    }
}

impl DiagnosticWithFix for MissingOkInTailExpr {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let tail_expr = self.expr.to_node(&root);
        let tail_expr_range = tail_expr.syntax().text_range();
        let edit = TextEdit::replace(tail_expr_range, format!("Ok({})", tail_expr.syntax()));
        let source_change =
            SourceFileEdit { file_id: self.file.original_file(sema.db), edit }.into();
        Some(Fix::new("Wrap with ok", source_change, tail_expr_range))
    }
}

impl DiagnosticWithFix for IncorrectCase {
    fn fix(&self, sema: &Semantics<RootDatabase>) -> Option<Fix> {
        let root = sema.db.parse_or_expand(self.file)?;
        let name_node = self.ident.to_node(&root);

        let name_node = InFile::new(self.file, name_node.syntax());
        let frange = name_node.original_file_range(sema.db);
        let file_position = FilePosition { file_id: frange.file_id, offset: frange.range.start() };

        let rename_changes =
            rename_with_semantics(sema, file_position, &self.suggested_text).ok()?;

        let label = format!("Rename to {}", self.suggested_text);
        Some(Fix::new(&label, rename_changes.info, rename_changes.range))
    }
}

fn missing_record_expr_field_fix(
    sema: &Semantics<RootDatabase>,
    usage_file_id: FileId,
    record_expr_field: &ast::RecordExprField,
) -> Option<Fix> {
    let record_lit = ast::RecordExpr::cast(record_expr_field.syntax().parent()?.parent()?)?;
    let def_id = sema.resolve_variant(record_lit)?;
    let module;
    let def_file_id;
    let record_fields = match VariantDef::from(def_id) {
        VariantDef::Struct(s) => {
            module = s.module(sema.db);
            let source = s.source(sema.db);
            def_file_id = source.file_id;
            let fields = source.value.field_list()?;
            record_field_list(fields)?
        }
        VariantDef::Union(u) => {
            module = u.module(sema.db);
            let source = u.source(sema.db);
            def_file_id = source.file_id;
            source.value.record_field_list()?
        }
        VariantDef::EnumVariant(e) => {
            module = e.module(sema.db);
            let source = e.source(sema.db);
            def_file_id = source.file_id;
            let fields = source.value.field_list()?;
            record_field_list(fields)?
        }
    };
    let def_file_id = def_file_id.original_file(sema.db);

    let new_field_type = sema.type_of_expr(&record_expr_field.expr()?)?;
    if new_field_type.is_unknown() {
        return None;
    }
    let new_field = make::record_field(
        None,
        make::name(record_expr_field.field_name()?.text()),
        make::ty(&new_field_type.display_source_code(sema.db, module.into()).ok()?),
    );

    let last_field = record_fields.fields().last()?;
    let last_field_syntax = last_field.syntax();
    let indent = IndentLevel::from_node(last_field_syntax);

    let mut new_field = new_field.to_string();
    if usage_file_id != def_file_id {
        new_field = format!("pub(crate) {}", new_field);
    }
    new_field = format!("\n{}{}", indent, new_field);

    let needs_comma = !last_field_syntax.to_string().ends_with(',');
    if needs_comma {
        new_field = format!(",{}", new_field);
    }

    let source_change = SourceFileEdit {
        file_id: def_file_id,
        edit: TextEdit::insert(last_field_syntax.text_range().end(), new_field),
    };
    return Some(Fix::new(
        "Create field",
        source_change.into(),
        record_expr_field.syntax().text_range(),
    ));

    fn record_field_list(field_def_list: ast::FieldList) -> Option<ast::RecordFieldList> {
        match field_def_list {
            ast::FieldList::RecordFieldList(it) => Some(it),
            ast::FieldList::TupleFieldList(_) => None,
        }
    }
}
<|endoftext|>


<commit_before>#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate serde;

#[macro_use]
extern crate serde_derive;
extern crate rocket_contrib;

#[cfg(test)]
extern crate serde_json;

use rocket_contrib::Json;

mod nfa;

#[get("/")]
fn index() -> &'static str {
    //Render home page
    "Hello, World!"
}

// The type to represent the ID of a message.
type ID = usize;

#[derive(Serialize, Deserialize)]
struct Message {
        id: Option<ID>,
            contents: String
}

// curl -X POST --data '{"id": 1, "contents":"asdf"}' http://localhost:8000/test -H "Content-Type: application/json"
#[post("/test", format="application/json", data="<data>")]
fn test_thing(data: Json<Message>) -> &'static str {
    "it works!"
}

fn main() {
    rocket::ignite().mount("/", routes![index, test_thing]).launch();
}
<commit_msg>post for submit_nfa<commit_after>#![feature(plugin, custom_derive, custom_attribute)]
#![plugin(rocket_codegen)]
extern crate rocket;
extern crate serde;

#[macro_use]
extern crate serde_derive;
extern crate rocket_contrib;

#[cfg(test)]
extern crate serde_json;

use rocket_contrib::Json;
use nfa::*;

mod nfa;

#[get("/")]
fn index() -> &'static str {
    //Render home page
    "Hello, World!"
}

// The type to represent the ID of a message.
type ID = usize;

#[derive(Serialize, Deserialize)]
struct Message {
        id: Option<ID>,
            contents: String
}

// curl -X POST --data '{"id": 1, "contents":"asdf"}' http://localhost:8000/test -H "Content-Type: application/json"
#[post("/test", format="application/json", data="<data>")]
fn test_thing(data: Json<Message>) -> &'static str {
    "it works!"
}

#[post("/submit", format="application/json", data="<data>")]
fn submit_nfa(data: Json<Nfa<Unsanitary>>) -> &'static str {
    "it works!"
}

fn main() {
    rocket::ignite().mount("/", routes![index, test_thing, submit_nfa]).launch();
}
<|endoftext|>


<commit_before>use super::{ErrorCode, IndyHandle};

use utils::timeout::TimeoutUtils;

use libc::c_char;
use std::ffi::CString;
use std::sync::mpsc::channel;

pub struct Did {}

impl Did {
    pub fn new(wallet_handle: IndyHandle, my_did_json: &str) -> Result<(String, String), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err, did, verkey| {
            sender.send((err, did, verkey)).unwrap();
        });

        let (command_handle, cb) = Did::closure_to_create_and_store_my_did_cb(cb);

        let my_did_json = CString::new(my_did_json).unwrap();

        let err = unsafe {
            indy_create_and_store_my_did(command_handle,
                                         wallet_handle,
                                         my_did_json.as_ptr(),
                                         cb)
        };

        if err != ErrorCode::Success {
            return Err(err);
        }

        let (err, my_did, my_verkey) = receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok((my_did, my_verkey))
    }

    pub fn set_metadata(wallet_handle: i32, did: &str, metadata: &str) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();
        let cb = Box::new(move |err| {
            sender.send((err)).unwrap();
        });
        let (command_handle, callback) = Did::closure_to_store_did_metadata_cb(cb);

        let did = CString::new(did).unwrap();
        let metadata = CString::new(metadata).unwrap();

        let err = unsafe {
            indy_set_did_metadata(command_handle,
                                  wallet_handle,
                                  did.as_ptr(),
                                  metadata.as_ptr(),
                                  callback)
        };

        if err != ErrorCode::Success {
            return Err(err);
        }
        let err = receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap();
        if err != ErrorCode::Success {
            return Err(err);
        }
        Ok(())
    }

    pub fn closure_to_create_and_store_my_did_cb(closure: Box<FnMut(ErrorCode, String, String) + Send>) -> (i32,
                                                                                Option<extern fn(command_handle: i32,
                                                                                err: ErrorCode,
                                                                                did: *const c_char,
                                                                                verkey: *const c_char)>) {
        super::callbacks::_closure_to_cb_ec_string_string(closure)
    }

    pub fn closure_to_store_did_metadata_cb(closure: Box<FnMut(ErrorCode) + Send>) -> (i32,
                                                                                Option<extern fn(command_handle: i32,
                                                                                err: ErrorCode)>) {
        super::callbacks::_closure_to_cb_ec(closure)
    }
}

extern {
    #[no_mangle]
    pub fn indy_create_and_store_my_did(command_handle: i32,
                                        wallet_handle: i32,
                                        did_json: *const c_char,
                                        cb: Option<extern fn(xcommand_handle: i32, err: ErrorCode,
                                                             did: *const c_char,
                                                             verkey: *const c_char)>) -> ErrorCode;

    #[no_mangle]
    fn indy_set_did_metadata(command_handle: i32,
                             wallet_handle: i32,
                             did: *const c_char,
                             metadata: *const c_char,
                             cb: Option<extern fn(command_handle_: i32,
                                                  err: ErrorCode)>) -> ErrorCode;
}<commit_msg>[cli] Add ffi for list DIDs.<commit_after>use super::{ErrorCode, IndyHandle};

use utils::timeout::TimeoutUtils;

use libc::c_char;
use std::ffi::CString;
use std::sync::mpsc::channel;

pub struct Did {}

impl Did {
    pub fn new(wallet_handle: IndyHandle, my_did_json: &str) -> Result<(String, String), ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err, did, verkey| {
            sender.send((err, did, verkey)).unwrap();
        });

        let (command_handle, cb) = Did::closure_to_create_and_store_my_did_cb(cb);

        let my_did_json = CString::new(my_did_json).unwrap();

        let err = unsafe {
            indy_create_and_store_my_did(command_handle,
                                         wallet_handle,
                                         my_did_json.as_ptr(),
                                         cb)
        };

        if err != ErrorCode::Success {
            return Err(err);
        }

        let (err, my_did, my_verkey) = receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok((my_did, my_verkey))
    }

    pub fn set_metadata(wallet_handle: i32, did: &str, metadata: &str) -> Result<(), ErrorCode> {
        let (sender, receiver) = channel();
        let cb = Box::new(move |err| {
            sender.send((err)).unwrap();
        });
        let (command_handle, callback) = Did::closure_to_store_did_metadata_cb(cb);

        let did = CString::new(did).unwrap();
        let metadata = CString::new(metadata).unwrap();

        let err = unsafe {
            indy_set_did_metadata(command_handle,
                                  wallet_handle,
                                  did.as_ptr(),
                                  metadata.as_ptr(),
                                  callback)
        };

        if err != ErrorCode::Success {
            return Err(err);
        }
        let err = receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap();
        if err != ErrorCode::Success {
            return Err(err);
        }
        Ok(())
    }

    pub fn list_dids_with_meta(wallet_handle: i32) -> Result<String, ErrorCode> {
        let (sender, receiver) = channel();

        let cb = Box::new(move |err, dids| {
            sender.send((err, dids)).unwrap();
        });

        let (command_handle, cb) = Did::closure_to_list_dids_with_meta(cb);

        let err = unsafe {
            indy_list_my_dids_with_meta(command_handle, wallet_handle, cb)
        };

        if err != ErrorCode::Success {
            return Err(err);
        }

        let (err, dids) = receiver.recv_timeout(TimeoutUtils::long_timeout()).unwrap();

        if err != ErrorCode::Success {
            return Err(err);
        }

        Ok(dids)
    }

    pub fn closure_to_create_and_store_my_did_cb(closure: Box<FnMut(ErrorCode, String, String) + Send>) -> (i32,
                                                                                Option<extern fn(command_handle: i32,
                                                                                err: ErrorCode,
                                                                                did: *const c_char,
                                                                                verkey: *const c_char)>) {
        super::callbacks::_closure_to_cb_ec_string_string(closure)
    }

    pub fn closure_to_store_did_metadata_cb(closure: Box<FnMut(ErrorCode) + Send>) -> (i32,
                                                                                Option<extern fn(command_handle: i32,
                                                                                err: ErrorCode)>) {
        super::callbacks::_closure_to_cb_ec(closure)
    }

    fn closure_to_list_dids_with_meta(closure: Box<FnMut(ErrorCode, String) + Send>)
                                      -> (i32,
                                          Option<extern fn(command_handle: i32, err: ErrorCode,
                                                           dids: *const c_char)>) {
        super::callbacks::_closure_to_cb_ec_string(closure)
    }
}

extern {
    #[no_mangle]
    pub fn indy_create_and_store_my_did(command_handle: i32,
                                        wallet_handle: i32,
                                        did_json: *const c_char,
                                        cb: Option<extern fn(xcommand_handle: i32, err: ErrorCode,
                                                             did: *const c_char,
                                                             verkey: *const c_char)>) -> ErrorCode;

    #[no_mangle]
    fn indy_set_did_metadata(command_handle: i32,
                             wallet_handle: i32,
                             did: *const c_char,
                             metadata: *const c_char,
                             cb: Option<extern fn(command_handle_: i32,
                                                  err: ErrorCode)>) -> ErrorCode;

    #[no_mangle]
    fn indy_list_my_dids_with_meta(command_handle: i32,
                                   wallet_handle: i32,
                                   cb: Option<extern fn(xcommand_handle: i32, err: ErrorCode,
                                                        dids: *const c_char)>) -> ErrorCode;
}<|endoftext|>


<commit_before>use std::fmt::Debug;
use adapton_syntax::*;
use adapton_sigs::*;
use std::rc::Rc;
use std::hash::{Hash,Hasher};

pub type Loc = usize;

#[derive(Debug,Clone,Hash,Eq,PartialEq)]
pub struct Name;

#[derive(Debug)]
pub struct Whatever;
pub struct AdaptonFromScratch {
    /// just need a store; the Adapton trait provides a store semantics
    store : Vec<Box<Whatever>>
}

impl Adapton for AdaptonFromScratch {
    type Name = Name;
    type Loc  = Loc;

    fn new () -> AdaptonFromScratch {
        AdaptonFromScratch {
            store : Vec::new (),
        }
    }

    fn name_of_string (self:&mut AdaptonFromScratch, sym:String) -> Name { Name }
    fn name_of_u64 (self:&mut AdaptonFromScratch, sym:u64) -> Name { Name }
    fn name_pair (self: &mut AdaptonFromScratch, fst:Name, snd:Name) -> Name { Name }
    fn name_fork (self:&mut AdaptonFromScratch, nm:Name) -> (Name, Name) { (Name,Name) }
    fn ns<T,F> (self: &mut AdaptonFromScratch, nm:Name, body:F) -> T where F:FnOnce(&mut AdaptonFromScratch) -> T { body(self) }
    fn put<T:Eq> (self:&mut AdaptonFromScratch, x:T) -> Art<T,Loc> { Art::Rc(Rc::new(x)) }

    fn cell<T:Eq+Debug+Clone
        +'static // TODO-Later: Needed on T because of lifetime issues.
        >
        (self:&mut AdaptonFromScratch, nm:Name, val:T) -> MutArt<T,Loc> {
            panic!("")
        }

    fn set<T:Eq+Debug> (self:&mut AdaptonFromScratch, cell:MutArt<T,Loc>, val:T) {
        panic!("")
    }

    fn thunk<Arg:Eq+Hash+Debug+Clone+'static,Spurious:'static+Clone,Res:Eq+Debug+Clone+'static>
        (self:&mut AdaptonFromScratch,
         id:ArtIdChoice<Name>,
         prog_pt:ProgPt,
         fn_box:Rc<Box<Fn(&mut AdaptonFromScratch, Arg, Spurious) -> Res>>,
         arg:Arg, spurious:Spurious)
         -> Art<Res,Loc>
    {
        panic!("")
    }

    fn force<T:'static+Eq+Debug+Clone> (self:&mut AdaptonFromScratch,
                                        art:&Art<T,Loc>) -> T
    {
        panic!("")
    }
}
<commit_msg>code-cloned App structure from AdaptonState<commit_after>use std::fmt::Debug;
use adapton_syntax::*;
use adapton_sigs::*;
use std::rc::Rc;
use std::hash::{Hash,Hasher};
use std::fmt::{Formatter,Result};

pub type Loc = usize;

#[derive(Debug,Clone,Hash,Eq,PartialEq)]
pub struct Name;

#[derive(Debug)]
pub struct Whatever;
pub struct AdaptonFromScratch {
    /// just need a store; the Adapton trait provides a store semantics
    store : Vec<Box<Whatever>>
}

impl Adapton for AdaptonFromScratch {
    type Name = Name;
    type Loc  = Loc;

    fn new () -> AdaptonFromScratch {
        AdaptonFromScratch {
            store : Vec::new (),
        }
    }

    fn name_of_string (self:&mut AdaptonFromScratch, sym:String) -> Name { Name }
    fn name_of_u64 (self:&mut AdaptonFromScratch, sym:u64) -> Name { Name }
    fn name_pair (self: &mut AdaptonFromScratch, fst:Name, snd:Name) -> Name { Name }
    fn name_fork (self:&mut AdaptonFromScratch, nm:Name) -> (Name, Name) { (Name,Name) }
    fn ns<T,F> (self: &mut AdaptonFromScratch, nm:Name, body:F) -> T where F:FnOnce(&mut AdaptonFromScratch) -> T { body(self) }
    fn put<T:Eq> (self:&mut AdaptonFromScratch, x:T) -> Art<T,Loc> { Art::Rc(Rc::new(x)) }

    fn cell<T:Eq+Debug+Clone
        +'static // TODO-Later: Needed on T because of lifetime issues.
        >
        (self:&mut AdaptonFromScratch, nm:Name, val:T) -> MutArt<T,Loc> {
            panic!("")
        }

    fn set<T:Eq+Debug> (self:&mut AdaptonFromScratch, cell:MutArt<T,Loc>, val:T) {
        panic!("")
    }

    fn thunk<Arg:Eq+Hash+Debug+Clone+'static,Spurious:'static+Clone,Res:Eq+Debug+Clone+'static>
        (self:&mut AdaptonFromScratch,
         id:ArtIdChoice<Name>,
         prog_pt:ProgPt,
         fn_box:Rc<Box<Fn(&mut AdaptonFromScratch, Arg, Spurious) -> Res>>,
         arg:Arg, spurious:Spurious)
         -> Art<Res,Loc>
    {
        panic!("")
    }

    fn force<T:'static+Eq+Debug+Clone> (self:&mut AdaptonFromScratch,
                                        art:&Art<T,Loc>) -> T
    {
        panic!("")
    }
}

// Produce a value of type Res.
trait Producer<Res> {
    fn produce(self:&Self, st:&mut AdaptonFromScratch) -> Res;
}

#[derive(Clone)]
struct App<Arg,Spurious,Res> {
    prog_pt:  ProgPt,
    fn_box:   Rc<Box<Fn(&mut AdaptonFromScratch, Arg, Spurious) -> Res>>,
    arg:      Arg,
    spurious: Spurious,
}

impl<Arg,Spurious,Res> Debug for App<Arg,Spurious,Res> {
    fn fmt(&self, f: &mut Formatter) -> Result { self.prog_pt.fmt(f) }
}

impl<Arg:Hash,Spurious,Res> Hash for App<Arg,Spurious,Res> {
    fn hash<H>(&self, state: &mut H) where H: Hasher { (&self.prog_pt,&self.arg).hash(state) }
}

impl<Arg:'static+PartialEq+Eq+Clone,Spurious:'static+Clone,Res:'static> Producer<Res>
    for App<Arg,Spurious,Res>
{
    fn produce(self:&Self, st:&mut AdaptonFromScratch) -> Res {
        let f = self.fn_box.clone() ;
        f (st,self.arg.clone(),self.spurious.clone())
    }
}
<|endoftext|>


<commit_before>// This benchmark suite contains some benchmarks along a set of dimensions:
//   Hasher: std default (SipHash) and crate default (FxHash).
//   Int key distribution: low bit heavy, top bit heavy, and random.
//   Task: basic functionality: insert, insert_erase, lookup, lookup_fail, iter
#![feature(test)]

extern crate test;

use test::{black_box, Bencher};

use hashbrown::HashMap;
use hashbrown::hash_map::DefaultHashBuilder;
use std::collections::hash_map::RandomState;

const SIZE: usize = 1000;

// The default hashmap when using this crate directly.
type FxHashMap<K, V> = HashMap<K, V, DefaultHashBuilder>;
// This uses the hashmap from this crate with the default hasher of the stdlib.
type StdHashMap<K, V> = HashMap<K, V, RandomState>;

// A random key iterator.
#[derive(Clone, Copy)]
struct RandomKeys {
    remaining: usize,
    state: usize,
}

impl RandomKeys {
    fn new(size: usize) -> Self {
        RandomKeys{
            remaining: size,
            state: 1,
        }
    }

    // Produce a different set of random values.
    fn new2(size: usize) -> Self {
        RandomKeys{
            remaining: size,
            state: 2,
        }
    }
}

impl Iterator for RandomKeys {
    type Item = usize;
    fn next(&mut self) -> Option<usize> {
        if self.remaining == 0 {
            None
        } else {
            self.remaining -= 1;
            // Multiply by some 32 bit prime.
            self.state = self.state.wrapping_mul(3787392781);
            // Mix in to the bottom bits which are constant mod powers of 2.
            Some(self.state ^ (self.state >> 4))
        }
    }
}

macro_rules! bench_insert {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            b.iter(|| {
                let mut m = $maptype::default();
                for i in $keydist {
                    m.insert(i, i);
                }
                black_box(m);
            })
        }
    }
}

bench_insert!(insert_fx_serial, FxHashMap, 0..SIZE);
bench_insert!(insert_std_serial, StdHashMap, 0..SIZE);
bench_insert!(insert_fx_highbits, FxHashMap, (0..SIZE).map(usize::swap_bytes));
bench_insert!(insert_std_highbits, StdHashMap, (0..SIZE).map(usize::swap_bytes));
bench_insert!(insert_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_insert!(insert_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_insert_erase {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            b.iter(|| {
                let mut m = $maptype::default();
                for i in $keydist {
                    m.insert(i, i);
                }
                black_box(&mut m);
                for i in $keydist {
                    m.remove(&i);
                }
                black_box(m);
            })
        }
    }
}

bench_insert_erase!(insert_erase_fx_serial, FxHashMap, 0..SIZE);
bench_insert_erase!(insert_erase_std_serial, StdHashMap, 0..SIZE);
bench_insert_erase!(insert_erase_fx_highbits, FxHashMap, (0..SIZE).map(usize::swap_bytes));
bench_insert_erase!(insert_erase_std_highbits, StdHashMap, (0..SIZE).map(usize::swap_bytes));
bench_insert_erase!(insert_erase_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_insert_erase!(insert_erase_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_lookup {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in $keydist {
                    black_box(m.get(&i));
                }
            })
        }
    }
}

bench_lookup!(lookup_fx_serial, FxHashMap, 0..SIZE);
bench_lookup!(lookup_std_serial, StdHashMap, 0..SIZE);
bench_lookup!(lookup_fx_highbits, FxHashMap, (0..SIZE).map(usize::swap_bytes));
bench_lookup!(lookup_std_highbits, StdHashMap, (0..SIZE).map(usize::swap_bytes));
bench_lookup!(lookup_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_lookup!(lookup_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_lookup_fail {
    ($name:ident, $maptype:ident, $keydist:expr, $keydist2:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in $keydist2 {
                    black_box(m.get(&i));
                }
            })
        }
    }
}

bench_lookup_fail!(lookup_fail_fx_serial, FxHashMap, 0..SIZE, SIZE..SIZE*2);
bench_lookup_fail!(lookup_fail_std_serial, StdHashMap, 0..SIZE, SIZE..SIZE*2);
bench_lookup_fail!(lookup_fail_fx_highbits, FxHashMap, (0..SIZE).map(usize::swap_bytes),
              (SIZE..SIZE*2).map(usize::swap_bytes));
bench_lookup_fail!(lookup_fail_std_highbits, StdHashMap, (0..SIZE).map(usize::swap_bytes),
              (SIZE..SIZE*2).map(usize::swap_bytes));
bench_lookup_fail!(lookup_fail_fx_random, FxHashMap, RandomKeys::new(SIZE), RandomKeys::new2(SIZE));
bench_lookup_fail!(lookup_fail_std_random, StdHashMap, RandomKeys::new(SIZE), RandomKeys::new2(SIZE));

macro_rules! bench_iter {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in &m {
                    black_box(i);
                }
            })
        }
    }
}

bench_iter!(iter_fx_serial, FxHashMap, 0..SIZE);
bench_iter!(iter_std_serial, StdHashMap, 0..SIZE);
bench_iter!(iter_fx_highbits, FxHashMap, (0..SIZE).map(usize::swap_bytes));
bench_iter!(iter_std_highbits, StdHashMap, (0..SIZE).map(usize::swap_bytes));
bench_iter!(iter_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_iter!(iter_std_random, StdHashMap, RandomKeys::new(SIZE));
<commit_msg>rustfmt macros<commit_after>// This benchmark suite contains some benchmarks along a set of dimensions:
//   Hasher: std default (SipHash) and crate default (FxHash).
//   Int key distribution: low bit heavy, top bit heavy, and random.
//   Task: basic functionality: insert, insert_erase, lookup, lookup_fail, iter
#![feature(test)]

extern crate test;

use test::{black_box, Bencher};

use hashbrown::hash_map::DefaultHashBuilder;
use hashbrown::HashMap;
use std::collections::hash_map::RandomState;

const SIZE: usize = 1000;

// The default hashmap when using this crate directly.
type FxHashMap<K, V> = HashMap<K, V, DefaultHashBuilder>;
// This uses the hashmap from this crate with the default hasher of the stdlib.
type StdHashMap<K, V> = HashMap<K, V, RandomState>;

// A random key iterator.
#[derive(Clone, Copy)]
struct RandomKeys {
    remaining: usize,
    state: usize,
}

impl RandomKeys {
    fn new(size: usize) -> Self {
        RandomKeys {
            remaining: size,
            state: 1,
        }
    }

    // Produce a different set of random values.
    fn new2(size: usize) -> Self {
        RandomKeys {
            remaining: size,
            state: 2,
        }
    }
}

impl Iterator for RandomKeys {
    type Item = usize;
    fn next(&mut self) -> Option<usize> {
        if self.remaining == 0 {
            None
        } else {
            self.remaining -= 1;
            // Multiply by some 32 bit prime.
            self.state = self.state.wrapping_mul(3787392781);
            // Mix in to the bottom bits which are constant mod powers of 2.
            Some(self.state ^ (self.state >> 4))
        }
    }
}

macro_rules! bench_insert {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            b.iter(|| {
                let mut m = $maptype::default();
                for i in $keydist {
                    m.insert(i, i);
                }
                black_box(m);
            })
        }
    };
}

bench_insert!(insert_fx_serial, FxHashMap, 0..SIZE);
bench_insert!(insert_std_serial, StdHashMap, 0..SIZE);
bench_insert!(
    insert_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_insert!(
    insert_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_insert!(insert_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_insert!(insert_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_insert_erase {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            b.iter(|| {
                let mut m = $maptype::default();
                for i in $keydist {
                    m.insert(i, i);
                }
                black_box(&mut m);
                for i in $keydist {
                    m.remove(&i);
                }
                black_box(m);
            })
        }
    };
}

bench_insert_erase!(insert_erase_fx_serial, FxHashMap, 0..SIZE);
bench_insert_erase!(insert_erase_std_serial, StdHashMap, 0..SIZE);
bench_insert_erase!(
    insert_erase_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_insert_erase!(
    insert_erase_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_insert_erase!(insert_erase_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_insert_erase!(insert_erase_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_lookup {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in $keydist {
                    black_box(m.get(&i));
                }
            })
        }
    };
}

bench_lookup!(lookup_fx_serial, FxHashMap, 0..SIZE);
bench_lookup!(lookup_std_serial, StdHashMap, 0..SIZE);
bench_lookup!(
    lookup_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_lookup!(
    lookup_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_lookup!(lookup_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_lookup!(lookup_std_random, StdHashMap, RandomKeys::new(SIZE));

macro_rules! bench_lookup_fail {
    ($name:ident, $maptype:ident, $keydist:expr, $keydist2:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in $keydist2 {
                    black_box(m.get(&i));
                }
            })
        }
    };
}

bench_lookup_fail!(lookup_fail_fx_serial, FxHashMap, 0..SIZE, SIZE..SIZE * 2);
bench_lookup_fail!(lookup_fail_std_serial, StdHashMap, 0..SIZE, SIZE..SIZE * 2);
bench_lookup_fail!(
    lookup_fail_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes),
    (SIZE..SIZE * 2).map(usize::swap_bytes)
);
bench_lookup_fail!(
    lookup_fail_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes),
    (SIZE..SIZE * 2).map(usize::swap_bytes)
);
bench_lookup_fail!(
    lookup_fail_fx_random,
    FxHashMap,
    RandomKeys::new(SIZE),
    RandomKeys::new2(SIZE)
);
bench_lookup_fail!(
    lookup_fail_std_random,
    StdHashMap,
    RandomKeys::new(SIZE),
    RandomKeys::new2(SIZE)
);

macro_rules! bench_iter {
    ($name:ident, $maptype:ident, $keydist:expr) => {
        #[bench]
        fn $name(b: &mut Bencher) {
            let mut m = $maptype::default();
            for i in $keydist {
                m.insert(i, i);
            }

            b.iter(|| {
                for i in &m {
                    black_box(i);
                }
            })
        }
    };
}

bench_iter!(iter_fx_serial, FxHashMap, 0..SIZE);
bench_iter!(iter_std_serial, StdHashMap, 0..SIZE);
bench_iter!(
    iter_fx_highbits,
    FxHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_iter!(
    iter_std_highbits,
    StdHashMap,
    (0..SIZE).map(usize::swap_bytes)
);
bench_iter!(iter_fx_random, FxHashMap, RandomKeys::new(SIZE));
bench_iter!(iter_std_random, StdHashMap, RandomKeys::new(SIZE));
<|endoftext|>