Repository: thrift
Updated Branches:
  refs/heads/master ee17ff95e -> 92e1c409c


THRIFT-4099: Derive Hash trait for Rust structs
Client: rs

This closes #1246


Project: http://git-wip-us.apache.org/repos/asf/thrift/repo
Commit: http://git-wip-us.apache.org/repos/asf/thrift/commit/92e1c409
Tree: http://git-wip-us.apache.org/repos/asf/thrift/tree/92e1c409
Diff: http://git-wip-us.apache.org/repos/asf/thrift/diff/92e1c409

Branch: refs/heads/master
Commit: 92e1c409c74632ea302eea48b1507e1121769a46
Parents: ee17ff9
Author: Allen George <[email protected]>
Authored: Thu Apr 6 08:28:22 2017 -0400
Committer: James E. King, III <[email protected]>
Committed: Fri Apr 7 09:24:41 2017 -0400

----------------------------------------------------------------------
 .../cpp/src/thrift/generate/t_rs_generator.cc   | 58 ++++++++++++++++----
 lib/rs/src/transport/mem.rs                     |  2 +-
 lib/rs/test/thrifts/Base_One.thrift             | 19 +++++++
 3 files changed, 67 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/thrift/blob/92e1c409/compiler/cpp/src/thrift/generate/t_rs_generator.cc
----------------------------------------------------------------------
diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc 
b/compiler/cpp/src/thrift/generate/t_rs_generator.cc
index 78794a5..c34ed17 100644
--- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc
+++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc
@@ -245,6 +245,13 @@ private:
   // rendered code is calling such a function it has to dereference `v`.
   bool needs_deref_on_container_write(t_type* ttype);
 
+  // Return the variable (including all dereferences) required to write values 
from a rust container
+  // to the output protocol. For example, if you were iterating through a 
container and using the temp
+  // variable `v` to represent each element, then `ttype` is the type stored 
in the container and
+  // `base_var` is "v". The return value is the actual string you will have to 
use to properly reference
+  // the temp variable for writing to the output protocol.
+  string string_container_write_variable(t_type* ttype, const string& 
base_var);
+
   // Write the code to read bytes from the wire into the given `t_struct`. 
`struct_name` is the
   // actual Rust name of the `t_struct`. If `struct_type` is `T_ARGS` then all 
struct fields are
   // necessary. Otherwise, the field's default optionality is used.
@@ -377,6 +384,9 @@ private:
   // Write the documentation for a struct, service-call or other 
documentation-annotated element.
   void render_rustdoc(t_doc* tdoc);
 
+  // Return `true` if the true type of `ttype` is a thrift double, `false` 
otherwise.
+  bool is_double(t_type* ttype);
+
   // Return a string representing the rust type given a `t_type`.
   string to_rust_type(t_type* ttype, bool ordered_float = true);
 
@@ -655,10 +665,7 @@ void t_rs_generator::render_const_value(t_type* ttype, 
t_const_value* tvalue) {
       f_gen_ << tvalue->get_integer();
       break;
     case t_base_type::TYPE_DOUBLE:
-      f_gen_
-        << indent()
-        << "OrderedFloat::from(" << tvalue->get_double() << ")"
-        << endl;
+      f_gen_ << "OrderedFloat::from(" << tvalue->get_double() << " as f64)";
       break;
     default:
       throw "cannot generate const value for " + 
t_base_type::t_base_name(tbase_type->get_base());
@@ -826,7 +833,7 @@ void t_rs_generator::generate_enum(t_enum* tenum) {
 
 void t_rs_generator::render_enum_definition(t_enum* tenum, const string& 
enum_name) {
   render_rustdoc((t_doc*) tenum);
-  f_gen_ << "#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]" << 
endl;
+  f_gen_ << "#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, 
PartialOrd)]" << endl;
   f_gen_ << "pub enum " << enum_name << " {" << endl;
   indent_up();
 
@@ -965,7 +972,7 @@ void t_rs_generator::render_struct_definition(
   t_rs_generator::e_struct_type struct_type
 ) {
   render_rustdoc((t_doc*) tstruct);
-  f_gen_ << "#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]" << endl;
+  f_gen_ << "#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]" << 
endl;
   f_gen_ << visibility_qualifier(struct_type) << "struct " << struct_name << " 
{" << endl;
 
   // render the members
@@ -1311,7 +1318,7 @@ void t_rs_generator::render_union_definition(const 
string& union_name, t_struct*
     throw "cannot generate rust enum with 0 members"; // may be valid thrift, 
but it's invalid rust
   }
 
-  f_gen_ << "#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]" << endl;
+  f_gen_ << "#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]" << 
endl;
   f_gen_ << "pub enum " << union_name << " {" << endl;
   indent_up();
 
@@ -1543,7 +1550,7 @@ void t_rs_generator::render_list_sync_write(const string 
&list_var, bool list_va
   string ref(list_var_is_ref ? "" : "&");
   f_gen_ << indent() << "for e in " << ref << list_var << " {" << endl;
   indent_up();
-  render_type_sync_write(needs_deref_on_container_write(elem_type) ? "*e" : 
"e", true, elem_type);
+  render_type_sync_write(string_container_write_variable(elem_type, "e"), 
true, elem_type);
   f_gen_ << indent() << "o_prot.write_list_end()?;" << endl;
   indent_down();
   f_gen_ << indent() << "}" << endl;
@@ -1564,7 +1571,7 @@ void t_rs_generator::render_set_sync_write(const string 
&set_var, bool set_var_i
   string ref(set_var_is_ref ? "" : "&");
   f_gen_ << indent() << "for e in " << ref << set_var << " {" << endl;
   indent_up();
-  render_type_sync_write(needs_deref_on_container_write(elem_type) ? "*e" : 
"e", true, elem_type);
+  render_type_sync_write(string_container_write_variable(elem_type, "e"), 
true, elem_type);
   f_gen_ << indent() << "o_prot.write_set_end()?;" << endl;
   indent_down();
   f_gen_ << indent() << "}" << endl;
@@ -1587,13 +1594,30 @@ void t_rs_generator::render_map_sync_write(const string 
&map_var, bool map_var_i
   string ref(map_var_is_ref ? "" : "&");
   f_gen_ << indent() << "for (k, v) in " << ref << map_var << " {" << endl;
   indent_up();
-  render_type_sync_write(needs_deref_on_container_write(key_type) ? "*k" : 
"k", true, key_type);
-  render_type_sync_write(needs_deref_on_container_write(val_type) ? "*v" : 
"v", true, val_type);
+  render_type_sync_write(string_container_write_variable(key_type, "k"), true, 
key_type);
+  render_type_sync_write(string_container_write_variable(val_type, "v"), true, 
val_type);
   f_gen_ << indent() << "o_prot.write_map_end()?;" << endl;
   indent_down();
   f_gen_ << indent() << "}" << endl;
 }
 
+string t_rs_generator::string_container_write_variable(t_type* ttype, const 
string& base_var) {
+  bool type_needs_deref = needs_deref_on_container_write(ttype);
+  bool type_is_double = is_double(ttype);
+
+  string write_variable;
+
+  if (type_is_double && type_needs_deref) {
+    write_variable = "(*" + base_var + ")";
+  } else if (type_needs_deref) {
+    write_variable = "*" + base_var;
+  } else {
+    write_variable = base_var;
+  }
+
+  return write_variable;
+}
+
 bool t_rs_generator::needs_deref_on_container_write(t_type* ttype) {
   ttype = get_true_type(ttype);
   return ttype->is_base_type() && !ttype->is_string();
@@ -2864,6 +2888,18 @@ void t_rs_generator::render_rift_error_struct(
   f_gen_ << indent() << ")" << endl;
 }
 
+bool t_rs_generator::is_double(t_type* ttype) {
+  ttype = get_true_type(ttype);
+  if (ttype->is_base_type()) {
+    t_base_type::t_base tbase = ((t_base_type*)ttype)->get_base();
+    if (tbase == t_base_type::TYPE_DOUBLE) {
+      return true;
+    }
+  }
+
+  return false;
+}
+
 string t_rs_generator::to_rust_type(t_type* ttype, bool ordered_float) {
   // ttype = get_true_type(ttype); <-- recurses through as many typedef layers 
as necessary
   if (ttype->is_base_type()) {

http://git-wip-us.apache.org/repos/asf/thrift/blob/92e1c409/lib/rs/src/transport/mem.rs
----------------------------------------------------------------------
diff --git a/lib/rs/src/transport/mem.rs b/lib/rs/src/transport/mem.rs
index 8ec2a98..97ec503 100644
--- a/lib/rs/src/transport/mem.rs
+++ b/lib/rs/src/transport/mem.rs
@@ -109,7 +109,7 @@ impl TBufferTransport {
         let buf = {
             let b = self.write_buffer_as_ref();
             let mut b_ret = vec![0; b.len()];
-            b_ret.copy_from_slice(&b);
+            b_ret.copy_from_slice(b);
             b_ret
         };
 

http://git-wip-us.apache.org/repos/asf/thrift/blob/92e1c409/lib/rs/test/thrifts/Base_One.thrift
----------------------------------------------------------------------
diff --git a/lib/rs/test/thrifts/Base_One.thrift 
b/lib/rs/test/thrifts/Base_One.thrift
index ceb1207..3da083d 100644
--- a/lib/rs/test/thrifts/Base_One.thrift
+++ b/lib/rs/test/thrifts/Base_One.thrift
@@ -31,6 +31,10 @@ const i32 BoilingPoint = 100
 
 const list<Temperature> Temperatures = [10, 11, 22, 33]
 
+// IMPORTANT: temps should end with ".0" because this tests
+// that we don't have a problem with const float list generation
+const list<double> CommonTemperatures = [300.0, 450.0]
+
 const double MealsPerDay = 2.5;
 
 struct Noodle {
@@ -48,6 +52,21 @@ struct MeasuringSpoon {
   1: Size size
 }
 
+struct MeasuringCup {
+  1: double millis
+}
+
+union MeasuringAids {
+  1: MeasuringSpoon spoon
+  2: MeasuringCup cup
+}
+
+struct CookingTemperatures {
+  1: set<double> commonTemperatures
+  2: list<double> usedTemperatures
+  3: map<double, double> fahrenheitToCentigradeConversions
+}
+
 struct Recipe {
   1: string recipeName
   2: string cuisine

Reply via email to