From b6b6dc715c0073af76de8244191b18c43ed4d24d Mon Sep 17 00:00:00 2001 From: Jiayu Liu Date: Sat, 8 Oct 2022 14:28:44 +0800 Subject: [PATCH] rust to add uuid support --- .../cpp/src/thrift/generate/t_rs_generator.cc | 1334 ++++++++--------- lib/rs/Cargo.toml | 4 + lib/rs/src/errors.rs | 9 + lib/rs/src/protocol/binary.rs | 39 +- lib/rs/src/protocol/compact.rs | 10 + lib/rs/src/protocol/mod.rs | 18 +- lib/rs/src/protocol/multiplexed.rs | 4 + lib/rs/src/protocol/stored.rs | 4 + lib/rs/test/Cargo.toml | 1 + lib/rs/test/thrifts/Base_One.thrift | 1 + test/rs/Cargo.toml | 2 +- test/rs/Makefile.am | 4 +- test/rs/src/bin/test_client.rs | 6 + test/rs/src/bin/test_server.rs | 5 + 14 files changed, 697 insertions(+), 744 deletions(-) diff --git a/compiler/cpp/src/thrift/generate/t_rs_generator.cc b/compiler/cpp/src/thrift/generate/t_rs_generator.cc index f454d9b929..2742724a60 100644 --- a/compiler/cpp/src/thrift/generate/t_rs_generator.cc +++ b/compiler/cpp/src/thrift/generate/t_rs_generator.cc @@ -17,11 +17,11 @@ * under the License. */ -#include #include +#include -#include "thrift/platform.h" #include "thrift/generate/t_generator.h" +#include "thrift/platform.h" using std::map; using std::ofstream; @@ -34,25 +34,17 @@ using std::vector; static const string endl("\n"); // avoid ostream << std::endl flushes static const string SERVICE_RESULT_VARIABLE("result_value"); static const string RESULT_STRUCT_SUFFIX("Result"); -static const string RUST_RESERVED_WORDS[] = { - "abstract", "alignof", "as", "become", - "box", "break", "const", "continue", - "crate", "do", "else", "enum", - "extern", "false", "final", "fn", - "for", "if", "impl", "in", - "let", "loop", "macro", "match", - "mod", "move", "mut", "offsetof", - "override", "priv", "proc", "pub", - "pure", "ref", "return", "Self", - "self", "sizeof", "static", "struct", - "super", "trait", "true", "type", - "typeof", "unsafe", "unsized", "use", - "virtual", "where", "while", "yield" -}; -const set RUST_RESERVED_WORDS_SET( - RUST_RESERVED_WORDS, - RUST_RESERVED_WORDS + sizeof(RUST_RESERVED_WORDS)/sizeof(RUST_RESERVED_WORDS[0]) -); +static const string RUST_RESERVED_WORDS[] + = {"abstract", "alignof", "as", "become", "box", "break", "const", "continue", "crate", + "do", "else", "enum", "extern", "false", "final", "fn", "for", "if", + "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", + "offsetof", "override", "priv", "proc", "pub", "pure", "ref", "return", "Self", + "self", "sizeof", "static", "struct", "super", "trait", "true", "type", "typeof", + "unsafe", "unsized", "use", "virtual", "where", "while", "yield"}; +const set RUST_RESERVED_WORDS_SET(RUST_RESERVED_WORDS, + RUST_RESERVED_WORDS + + sizeof(RUST_RESERVED_WORDS) + / sizeof(RUST_RESERVED_WORDS[0])); static const string SYNC_CLIENT_GENERIC_BOUND_VARS(""); static const string SYNC_CLIENT_GENERIC_BOUNDS("where IP: TInputProtocol, OP: TOutputProtocol"); @@ -62,11 +54,8 @@ static const string SYNC_CLIENT_GENERIC_BOUNDS("where IP: TInputProtocol, OP: TO class t_rs_generator : public t_generator { public: - t_rs_generator( - t_program* program, - const std::map&, - const std::string& - ) : t_generator(program) { + t_rs_generator(t_program* program, const std::map&, const std::string&) + : t_generator(program) { gen_dir_ = get_out_dir(); } @@ -107,7 +96,8 @@ class t_rs_generator : public t_generator { void render_attributes_and_includes(); // Create the closure of Rust modules referenced by this service. - void compute_service_referenced_modules(t_service *tservice, set> &referenced_modules); + void compute_service_referenced_modules(t_service* tservice, + set>& referenced_modules); // Write the rust representation of an enum. void render_enum_definition(t_enum* tenum, const string& enum_name); @@ -122,13 +112,16 @@ class t_rs_generator : public t_generator { // Write a simple rust const value (ie. `pub const FOO: foo...`). void render_const_value(const string& name, t_type* ttype, t_const_value* tvalue); - // Write a constant list, set, map or struct. These constants require allocation and cannot be defined - // using a 'pub const'. As a result, I create a holder struct with a single `const_value` method that - // returns the initialized instance. + // Write a constant list, set, map or struct. These constants require allocation and cannot be + // defined using a 'pub const'. As a result, I create a holder struct with a single `const_value` + // method that returns the initialized instance. void render_const_value_holder(const string& name, t_type* ttype, t_const_value* tvalue); // Write the actual const value - the right side of a const definition. - void render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned = true, bool is_inline = true); + void render_const_value(t_type* ttype, + t_const_value* tvalue, + bool is_owned = true, + bool is_inline = true); // Write a const struct (returned from `const_value` method). void render_const_struct(t_type* ttype, t_const_value* tvalue); @@ -142,12 +135,14 @@ class t_rs_generator : public t_generator { // Write a const map (returned from `const_value` method). void render_const_map(t_type* ttype, t_const_value* tvalue); - // Write the rust representation of a thrift struct to the generated file. Set `struct_type` to `T_ARGS` - // if rendering the struct used to pack arguments for a service call. When `struct_type` is `T_ARGS` the - // struct and its members have module visibility, and all fields are required. When `struct_type` is - // anything else the struct and its members have public visibility and fields have the visibility set - // in their definition. - void render_struct(const string& struct_name, t_struct* tstruct, t_rs_generator::e_struct_type struct_type); + // Write the rust representation of a thrift struct to the generated file. Set `struct_type` to + // `T_ARGS` if rendering the struct used to pack arguments for a service call. When `struct_type` + // is `T_ARGS` the struct and its members have module visibility, and all fields are required. + // When `struct_type` is anything else the struct and its members have public visibility and + // fields have the visibility set in their definition. + void render_struct(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type); // Write the comment block preceding a type definition (and implementation). void render_type_comment(const string& struct_name); @@ -156,79 +151,77 @@ class t_rs_generator : public t_generator { // user-defined structs and exception structs. The exact struct type to be generated is controlled // by the `struct_type` parameter, which (among other things) modifies the visibility of the // written struct and members, controls which trait implementations are generated. - void render_struct_definition( - const string& struct_name, - t_struct* tstruct, - t_rs_generator::e_struct_type struct_type - ); + void render_struct_definition(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type); // Writes the impl block associated with the rust representation of a struct. At minimum this // contains the methods to read from a protocol and write to a protocol. Additional methods may // be generated depending on `struct_type`. - void render_struct_impl( - const string& struct_name, - t_struct* tstruct, - t_rs_generator::e_struct_type struct_type - ); - - // Generate a `fn new(...)` for a struct with name `struct_name` and type `t_struct`. The auto-generated - // code may include generic type parameters to make the constructor more ergonomic. `struct_type` controls - // the visibility of the generated constructor. - void render_struct_constructor( - const string& struct_name, - t_struct* tstruct, - t_rs_generator::e_struct_type struct_type - ); - - // Write the `ok_or` method added to all Thrift service call result structs. You can use this method - // to convert a struct into a `Result` and use it in a `try!` or combinator chain. + void render_struct_impl(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type); + + // Generate a `fn new(...)` for a struct with name `struct_name` and type `t_struct`. The + // auto-generated code may include generic type parameters to make the constructor more ergonomic. + // `struct_type` controls the visibility of the generated constructor. + void render_struct_constructor(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type); + + // Write the `ok_or` method added to all Thrift service call result structs. You can use this + // method to convert a struct into a `Result` and use it in a `try!` or combinator chain. void render_result_struct_to_result_method(t_struct* tstruct); // Write the implementations for the `Error` and `Debug` traits. These traits are necessary for a // user-defined exception to be properly handled as Rust errors. void render_exception_struct_error_trait_impls(const string& struct_name, t_struct* tstruct); - // Write the function that serializes a struct to its wire representation. If `struct_type` is `T_ARGS` - // then all fields are considered "required", if not, the default optionality is used. - void render_struct_sync_write(t_struct *tstruct, t_rs_generator::e_struct_type struct_type); + // Write the function that serializes a struct to its wire representation. If `struct_type` is + // `T_ARGS` then all fields are considered "required", if not, the default optionality is used. + void render_struct_sync_write(t_struct* tstruct, t_rs_generator::e_struct_type struct_type); // Helper function that serializes a single struct field to its wire representation. Unpacks the - // variable (since it may be optional) and serializes according to the optionality rules required by `req`. - // Variables in auto-generated code are passed by reference. Since this function may be called in - // contexts where the variable is *already* a reference you can set `field_var_is_ref` to `true` to avoid - // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. - void render_struct_field_sync_write( - const string &field_var, - bool field_var_is_ref, - t_field *tfield, - t_field::e_req req); - - // Write the rust function that serializes a single type (i.e. a i32 etc.) to its wire representation. - // Variables in auto-generated code are passed by reference. Since this function may be called in - // contexts where the variable is *already* a reference you can set `type_var_is_ref` to `true` to avoid - // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. - void render_type_sync_write(const string &type_var, bool type_var_is_ref, t_type *ttype); + // variable (since it may be optional) and serializes according to the optionality rules required + // by `req`. Variables in auto-generated code are passed by reference. Since this function may be + // called in contexts where the variable is *already* a reference you can set `field_var_is_ref` + // to `true` to avoid generating an extra, unnecessary `&` that the compiler will have to + // automatically dereference. + void render_struct_field_sync_write(const string& field_var, + bool field_var_is_ref, + t_field* tfield, + t_field::e_req req); + + // Write the rust function that serializes a single type (i.e. a i32 etc.) to its wire + // representation. Variables in auto-generated code are passed by reference. Since this function + // may be called in contexts where the variable is *already* a reference you can set + // `type_var_is_ref` to `true` to avoid generating an extra, unnecessary `&` that the compiler + // will have to automatically dereference. + void render_type_sync_write(const string& type_var, bool type_var_is_ref, t_type* ttype); // Write a list to the output protocol. `list_variable` is the variable containing the list // that will be written to the output protocol. // Variables in auto-generated code are passed by reference. Since this function may be called in - // contexts where the variable is *already* a reference you can set `list_var_is_ref` to `true` to avoid - // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. - void render_list_sync_write(const string &list_var, bool list_var_is_ref, t_list *tlist); + // contexts where the variable is *already* a reference you can set `list_var_is_ref` to `true` to + // avoid generating an extra, unnecessary `&` that the compiler will have to automatically + // dereference. + void render_list_sync_write(const string& list_var, bool list_var_is_ref, t_list* tlist); // Write a set to the output protocol. `set_variable` is the variable containing the set that will // be written to the output protocol. // Variables in auto-generated code are passed by reference. Since this function may be called in - // contexts where the variable is *already* a reference you can set `set_var_is_ref` to `true` to avoid - // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. - void render_set_sync_write(const string &set_var, bool set_var_is_ref, t_set *tset); + // contexts where the variable is *already* a reference you can set `set_var_is_ref` to `true` to + // avoid generating an extra, unnecessary `&` that the compiler will have to automatically + // dereference. + void render_set_sync_write(const string& set_var, bool set_var_is_ref, t_set* tset); // Write a map to the output protocol. `map_variable` is the variable containing the map that will // be written to the output protocol. // Variables in auto-generated code are passed by reference. Since this function may be called in - // contexts where the variable is *already* a reference you can set `map_var_is_ref` to `true` to avoid - // generating an extra, unnecessary `&` that the compiler will have to automatically dereference. - void render_map_sync_write(const string &map_var, bool map_var_is_ref, t_map *tset); + // contexts where the variable is *already* a reference you can set `map_var_is_ref` to `true` to + // avoid generating an extra, unnecessary `&` that the compiler will have to automatically + // dereference. + void render_map_sync_write(const string& map_var, bool map_var_is_ref, t_map* tset); // Return `true` if we need to dereference ths type when writing an element from a container. // Iterations on rust containers are performed as follows: `for v in &values { ... }` @@ -237,38 +230,41 @@ class t_rs_generator : public t_generator { 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. + // 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. - void render_struct_sync_read(const string &struct_name, t_struct *tstruct, t_rs_generator::e_struct_type struct_type); + void render_struct_sync_read(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type); - // Write the rust function that deserializes a single type (i.e. i32 etc.) from its wire representation. - // Set `is_boxed` to `true` if the resulting value should be wrapped in a `Box::new(...)`. - void render_type_sync_read(const string &type_var, t_type *ttype, bool is_boxed = false); + // Write the rust function that deserializes a single type (i.e. i32 etc.) from its wire + // representation. Set `is_boxed` to `true` if the resulting value should be wrapped in a + // `Box::new(...)`. + void render_type_sync_read(const string& type_var, t_type* ttype, bool is_boxed = false); // Read the wire representation of a list and convert it to its corresponding rust implementation. // The deserialized list is stored in `list_variable`. - void render_list_sync_read(t_list *tlist, const string &list_variable); + void render_list_sync_read(t_list* tlist, const string& list_variable); // Read the wire representation of a set and convert it to its corresponding rust implementation. // The deserialized set is stored in `set_variable`. - void render_set_sync_read(t_set *tset, const string &set_variable); + void render_set_sync_read(t_set* tset, const string& set_variable); // Read the wire representation of a map and convert it to its corresponding rust implementation. // The deserialized map is stored in `map_variable`. - void render_map_sync_read(t_map *tmap, const string &map_variable); + void render_map_sync_read(t_map* tmap, const string& map_variable); // Return a temporary variable used to store values when deserializing nested containers. string struct_field_read_temp_variable(t_field* tfield); - // Top-level function that calls the various render functions necessary to write the rust representation - // of a thrift union (i.e. an enum). + // Top-level function that calls the various render functions necessary to write the rust + // representation of a thrift union (i.e. an enum). void render_union(t_struct* tstruct); // Write the enum corresponding to the Thrift union. @@ -278,20 +274,21 @@ class t_rs_generator : public t_generator { void render_union_impl(const string& union_name, t_struct* tstruct); // Write the `ENUM::write_to_out_protocol` function. - void render_union_sync_write(const string &union_name, t_struct *tstruct); + void render_union_sync_write(const string& union_name, t_struct* tstruct); // Write the `ENUM::read_from_in_protocol` function. - void render_union_sync_read(const string &union_name, t_struct *tstruct); + void render_union_sync_read(const string& union_name, t_struct* tstruct); - // Top-level function that calls the various render functions necessary to write the rust representation - // of a Thrift client. + // Top-level function that calls the various render functions necessary to write the rust + // representation of a Thrift client. void render_sync_client(t_service* tservice); // Write the trait with the service-call methods for `tservice`. - void render_sync_client_trait(t_service *tservice); + void render_sync_client_trait(t_service* tservice); - // Write the trait to be implemented by the client impl if end users can use it to make service calls. - void render_sync_client_marker_trait(t_service *tservice); + // Write the trait to be implemented by the client impl if end users can use it to make service + // calls. + void render_sync_client_marker_trait(t_service* tservice); // Write the code to create the Thrift service sync client struct and its matching 'impl' block. void render_sync_client_definition_and_impl(const string& client_impl_name); @@ -303,14 +300,14 @@ class t_rs_generator : public t_generator { // Write the code to create the impl block for the `TThriftClient` trait. Since generated // Rust Thrift clients perform all their operations using methods defined in this trait, we // have to implement it for the client structs. - void render_sync_client_tthriftclient_impl(const string &client_impl_name); + void render_sync_client_tthriftclient_impl(const string& client_impl_name); // Write the marker traits for any service(s) being extended, including the one for the current // service itself (i.e. `tservice`) - void render_sync_client_marker_trait_impls(t_service *tservice, const string &impl_struct_name); + void render_sync_client_marker_trait_impls(t_service* tservice, const string& impl_struct_name); // Generate a list of all the traits this Thrift client struct extends. - string sync_client_marker_traits_for_extension(t_service *tservice); + string sync_client_marker_traits_for_extension(t_service* tservice); // Top-level function that writes the code to make the Thrift service calls. void render_sync_client_process_impl(t_service* tservice); @@ -318,26 +315,28 @@ class t_rs_generator : public t_generator { // Write the actual function that calls out to the remote service and processes its response. void render_sync_send_recv_wrapper(t_function* tfunc); - // Write the `send` functionality for a Thrift service call represented by a `t_service->t_function`. + // Write the `send` functionality for a Thrift service call represented by a + // `t_service->t_function`. void render_sync_send(t_function* tfunc); - // Write the `recv` functionality for a Thrift service call represented by a `t_service->t_function`. - // This method is only rendered if the function is *not* oneway. + // Write the `recv` functionality for a Thrift service call represented by a + // `t_service->t_function`. This method is only rendered if the function is *not* oneway. void render_sync_recv(t_function* tfunc); - void render_sync_processor(t_service *tservice); + void render_sync_processor(t_service* tservice); - void render_sync_handler_trait(t_service *tservice); - void render_sync_processor_definition_and_impl(t_service *tservice); - void render_sync_process_delegation_functions(t_service *tservice); - void render_sync_process_function(t_function *tfunc, const string &handler_type); + void render_sync_handler_trait(t_service* tservice); + void render_sync_processor_definition_and_impl(t_service* tservice); + void render_sync_process_delegation_functions(t_service* tservice); + void render_sync_process_function(t_function* tfunc, const string& handler_type); void render_process_match_statements(t_service* tservice); - void render_sync_handler_succeeded(t_function *tfunc); - void render_sync_handler_failed(t_function *tfunc); - void render_sync_handler_failed_user_exception_branch(t_function *tfunc); - void render_sync_handler_failed_application_exception_branch(t_function *tfunc, const string &app_err_var); - void render_sync_handler_failed_default_exception_branch(t_function *tfunc); - void render_sync_handler_send_exception_response(t_function *tfunc, const string &err_var); + void render_sync_handler_succeeded(t_function* tfunc); + void render_sync_handler_failed(t_function* tfunc); + void render_sync_handler_failed_user_exception_branch(t_function* tfunc); + void render_sync_handler_failed_application_exception_branch(t_function* tfunc, + const string& app_err_var); + void render_sync_handler_failed_default_exception_branch(t_function* tfunc); + void render_sync_handler_send_exception_response(t_function* tfunc, const string& err_var); void render_service_call_structs(t_service* tservice); void render_service_call_args_struct(t_function* tfunc); void render_service_call_result_value_struct(t_function* tfunc); @@ -345,12 +344,10 @@ class t_rs_generator : public t_generator { string handler_successful_return_struct(t_function* tfunc); // Writes the result of `render_thrift_error_struct` wrapped in an `Err(thrift::Error(...))`. - void render_thrift_error( - const string& error_kind, - const string& error_struct, - const string& sub_error_kind, - const string& error_message - ); + void render_thrift_error(const string& error_kind, + const string& error_struct, + const string& sub_error_kind, + const string& error_message); // Write a thrift::Error variant struct. Error structs take the form: // ``` @@ -366,11 +363,9 @@ class t_rs_generator : public t_generator { // message: "This is some error message", // } // ``` - void render_thrift_error_struct( - const string& error_struct, - const string& sub_error_kind, - const string& error_message - ); + void render_thrift_error_struct(const string& error_struct, + const string& sub_error_kind, + const string& error_message); // Return a string containing all the unpacked service call args given a service call function // `t_function`. Prepends the args with either `&mut self` or `&self` and includes the arg types @@ -383,8 +378,8 @@ class t_rs_generator : public t_generator { // `field_prefix`, for example: `self.field_0`. string rust_sync_service_call_invocation(t_function* tfunc, const string& field_prefix = ""); - // Return a string containing all fields in the struct `tstruct` for use in a function declaration. - // Each field is followed by its type, for example: `field_0: String`. + // Return a string containing all fields in the struct `tstruct` for use in a function + // declaration. Each field is followed by its type, for example: `field_0: String`. string struct_to_declaration(t_struct* tstruct, t_rs_generator::e_struct_type struct_type); // Return a string containing all fields in the struct `tstruct` for use in a function call, @@ -413,7 +408,8 @@ class t_rs_generator : public t_generator { // Return `true` if we can write a const of the form `pub const FOO: ...`. bool can_generate_simple_const(t_type* ttype); - // Return `true` if we cannot write a standard Rust constant (because the type needs some allocation). + // Return `true` if we cannot write a standard Rust constant (because the type needs some + // allocation). bool can_generate_const_holder(t_type* ttype); // Return `true` if this type is a void, and should be represented by the rust `()` type. @@ -421,8 +417,9 @@ class t_rs_generator : public t_generator { t_field::e_req actual_field_req(t_field* tfield, t_rs_generator::e_struct_type struct_type); - // Return `true` if this `t_field::e_req` is either `t_field::T_OPTIONAL` or `t_field::T_OPT_IN_REQ_OUT` - // and needs to be wrapped by an `Option`, `false` otherwise. + // Return `true` if this `t_field::e_req` is either `t_field::T_OPTIONAL` or + // `t_field::T_OPT_IN_REQ_OUT` and needs to be wrapped by an `Option`, `false` + // otherwise. bool is_optional(t_field::e_req req); // Return `true` if the service call has arguments, `false` otherwise. @@ -431,30 +428,32 @@ class t_rs_generator : public t_generator { // Return `true` if a service call has non-`()` arguments, `false` otherwise. bool has_non_void_args(t_function* tfunc); - // Return `pub ` (notice trailing whitespace!) if the struct should be public, `` (empty string) otherwise. + // Return `pub ` (notice trailing whitespace!) if the struct should be public, `` (empty string) + // otherwise. string visibility_qualifier(t_rs_generator::e_struct_type struct_type); - // Returns the namespace prefix for a given Thrift service. If the type is defined in the presently-computed - // Thrift program, then an empty string is returned. + // Returns the namespace prefix for a given Thrift service. If the type is defined in the + // presently-computed Thrift program, then an empty string is returned. string rust_namespace(t_service* tservice); - // Returns the namespace prefix for a given Thrift type. If the type is defined in the presently-computed - // Thrift program, then an empty string is returned. + // Returns the namespace prefix for a given Thrift type. If the type is defined in the + // presently-computed Thrift program, then an empty string is returned. string rust_namespace(t_type* ttype); - // Returns the camel-cased name for a Rust struct type. Handles the case where `tstruct->get_name()` is - // a reserved word. + // Returns the camel-cased name for a Rust struct type. Handles the case where + // `tstruct->get_name()` is a reserved word. string rust_struct_name(t_struct* tstruct); // Returns the snake-cased name for a Rust field or local variable. Handles the case where // `tfield->get_name()` is a reserved word. string rust_field_name(t_field* tstruct); - // Returns the camel-cased name for a Rust union type. Handles the case where `tstruct->get_name()` is - // a reserved word. + // Returns the camel-cased name for a Rust union type. Handles the case where + // `tstruct->get_name()` is a reserved word. string rust_union_field_name(t_field* tstruct); - // Converts any variable name into a 'safe' variant that does not clash with any Rust reserved keywords. + // Converts any variable name into a 'safe' variant that does not clash with any Rust reserved + // keywords. string rust_safe_name(const string& name); // Return `true` if the name is a reserved Rust keyword, `false` otherwise. @@ -463,7 +462,8 @@ class t_rs_generator : public t_generator { // Return the name of the function that users will invoke to make outgoing service calls. string service_call_client_function_name(t_function* tfunc); - // Return the name of the function that users will have to implement to handle incoming service calls. + // Return the name of the function that users will have to implement to handle incoming service + // calls. string service_call_handler_function_name(t_function* tfunc); // Return the name of the struct used to pack the arguments for the thrift service call. @@ -481,7 +481,8 @@ class t_rs_generator : public t_generator { // Return the name for the sync service client struct given a `t_service`. string rust_sync_client_impl_name(t_service* tservice); - // Return the trait name that users will have to implement for the server half of a Thrift service. + // Return the trait name that users will have to implement for the server half of a Thrift + // service. string rust_sync_handler_trait_name(t_service* tservice); // Return the struct name for the server half of a Thrift service. @@ -489,7 +490,7 @@ class t_rs_generator : public t_generator { // Return the struct name for the struct that contains all the service-call implementations for // the server half of a Thrift service. - string rust_sync_processor_impl_name(t_service *tservice); + string rust_sync_processor_impl_name(t_service* tservice); // Return the variant name for an enum variant string rust_enum_variant_name(const string& name); @@ -537,14 +538,17 @@ void t_rs_generator::render_attributes_and_includes() { // code might not include imports from crates f_gen_ << "#![allow(unused_extern_crates)]" << endl; // constructors take *all* struct parameters, which can trigger the "too many arguments" warning - // some auto-gen'd types can be deeply nested. clippy recommends factoring them out which is hard to autogen - // some methods may start with "is_" - // FIXME: re-enable the 'vec_box' lint see: [THRIFT-5364](https://issues.apache.org/jira/browse/THRIFT-5364) - // This can happen because we automatically generate a Vec> when the type is a typedef - // and it's a forward typedef. This (typedef + forward typedef) can happen in two situations: + // some auto-gen'd types can be deeply nested. clippy recommends factoring them out which is hard + // to autogen some methods may start with "is_" + // FIXME: re-enable the 'vec_box' lint see: + // [THRIFT-5364](https://issues.apache.org/jira/browse/THRIFT-5364) This can happen because we + // automatically generate a Vec> when the type is a typedef and it's a forward typedef. + // This (typedef + forward typedef) can happen in two situations: // 1. When the type is recursive // 2. When you define types out of order - f_gen_ << "#![allow(clippy::too_many_arguments, clippy::type_complexity, clippy::vec_box, clippy::wrong_self_convention)]" << endl; + f_gen_ << "#![allow(clippy::too_many_arguments, clippy::type_complexity, clippy::vec_box, " + "clippy::wrong_self_convention)]" + << endl; // prevent rustfmt from running against this file // lines are too long, code is (thankfully!) not visual-indented, etc. // can't use #[rustfmt::skip] see: https://github.com/rust-lang/rust/issues/54726 @@ -562,8 +566,13 @@ void t_rs_generator::render_attributes_and_includes() { f_gen_ << "use std::rc::Rc;" << endl; f_gen_ << endl; f_gen_ << "use thrift::OrderedFloat;" << endl; - f_gen_ << "use thrift::{ApplicationError, ApplicationErrorKind, ProtocolError, ProtocolErrorKind, TThriftClient};" << endl; - f_gen_ << "use thrift::protocol::{TFieldIdentifier, TListIdentifier, TMapIdentifier, TMessageIdentifier, TMessageType, TInputProtocol, TOutputProtocol, TSerializable, TSetIdentifier, TStructIdentifier, TType};" << endl; + f_gen_ << "use thrift::{ApplicationError, ApplicationErrorKind, ProtocolError, " + "ProtocolErrorKind, TThriftClient};" + << endl; + f_gen_ << "use thrift::protocol::{TFieldIdentifier, TListIdentifier, TMapIdentifier, " + "TMessageIdentifier, TMessageType, TInputProtocol, TOutputProtocol, TSerializable, " + "TSetIdentifier, TStructIdentifier, TType};" + << endl; f_gen_ << "use thrift::protocol::field_id;" << endl; f_gen_ << "use thrift::protocol::verify_expected_message_type;" << endl; f_gen_ << "use thrift::protocol::verify_expected_sequence_number;" << endl; @@ -574,18 +583,21 @@ void t_rs_generator::render_attributes_and_includes() { // add all the program includes // NOTE: this is more involved than you would expect because of service extension - // Basically, I have to find the closure of all the services and include their modules at the top-level + // Basically, I have to find the closure of all the services and include their modules at the + // top-level set> referenced_modules; // set // first, start by adding explicit thrift includes const vector includes = get_program()->get_includes(); vector::const_iterator includes_iter; - for(includes_iter = includes.begin(); includes_iter != includes.end(); ++includes_iter) { - referenced_modules.insert(std::make_pair((*includes_iter)->get_name(), (*includes_iter)->get_namespace("rs"))); + for (includes_iter = includes.begin(); includes_iter != includes.end(); ++includes_iter) { + referenced_modules.insert( + std::make_pair((*includes_iter)->get_name(), (*includes_iter)->get_namespace("rs"))); } - // next, recursively iterate through all the services and add the names of any programs they reference + // next, recursively iterate through all the services and add the names of any programs they + // reference const vector services = get_program()->get_services(); vector::const_iterator service_iter; for (service_iter = services.begin(); service_iter != services.end(); ++service_iter) { @@ -595,7 +607,8 @@ void t_rs_generator::render_attributes_and_includes() { // finally, write all the "pub use..." declarations if (!referenced_modules.empty()) { set>::iterator module_iter; - for (module_iter = referenced_modules.begin(); module_iter != referenced_modules.end(); ++module_iter) { + for (module_iter = referenced_modules.begin(); module_iter != referenced_modules.end(); + ++module_iter) { string module_name((*module_iter).first); string module_namespace((*module_iter).second); @@ -604,7 +617,8 @@ void t_rs_generator::render_attributes_and_includes() { if (module_namespace.empty()) { f_gen_ << "use crate::" << rust_snake_case(module_name) << ";" << endl; } else { - f_gen_ << "use crate::" << module_namespace << "::" << rust_snake_case(module_name) << ";" << endl; + f_gen_ << "use crate::" << module_namespace << "::" << rust_snake_case(module_name) << ";" + << endl; } } f_gen_ << endl; @@ -612,13 +626,13 @@ void t_rs_generator::render_attributes_and_includes() { } void t_rs_generator::compute_service_referenced_modules( - t_service *tservice, - set> &referenced_modules -) { + t_service* tservice, + set>& referenced_modules) { t_service* extends = tservice->get_extends(); if (extends) { if (extends->get_program() != get_program()) { - referenced_modules.insert(std::make_pair(extends->get_program()->get_name(), extends->get_program()->get_namespace("rs"))); + referenced_modules.insert(std::make_pair(extends->get_program()->get_name(), + extends->get_program()->get_namespace("rs"))); } compute_service_referenced_modules(extends, referenced_modules); } @@ -663,7 +677,9 @@ void t_rs_generator::render_const_value(const string& name, t_type* ttype, t_con f_gen_ << endl; } -void t_rs_generator::render_const_value_holder(const string& name, t_type* ttype, t_const_value* tvalue) { +void t_rs_generator::render_const_value_holder(const string& name, + t_type* ttype, + t_const_value* tvalue) { if (!can_generate_const_holder(ttype)) { throw "cannot generate constant holder for " + ttype->get_name(); } @@ -685,7 +701,10 @@ void t_rs_generator::render_const_value_holder(const string& name, t_type* ttype f_gen_ << endl; } -void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bool is_owned, bool is_inline) { +void t_rs_generator::render_const_value(t_type* ttype, + t_const_value* tvalue, + bool is_owned, + bool is_inline) { if (!is_inline) { f_gen_ << indent(); } @@ -696,7 +715,8 @@ void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bo case t_base_type::TYPE_STRING: if (tbase_type->is_binary()) { if (is_owned) { - f_gen_ << "\"" << tvalue->get_string() << "\""<< ".to_owned().into_bytes()"; + f_gen_ << "\"" << tvalue->get_string() << "\"" + << ".to_owned().into_bytes()"; } else { f_gen_ << "b\"" << tvalue->get_string() << "\""; } @@ -707,6 +727,9 @@ void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bo } } break; + case t_base_type::TYPE_UUID: + f_gen_ << "Uuid::parse_str(\"" << tvalue->get_string() << "\").unwrap()"; + break; case t_base_type::TYPE_BOOL: f_gen_ << (tvalue->get_integer() ? "true" : "false"); break; @@ -727,13 +750,8 @@ void t_rs_generator::render_const_value(t_type* ttype, t_const_value* tvalue, bo } else if (ttype->is_enum()) { f_gen_ << "{" << endl; indent_up(); - f_gen_ - << indent() - << to_rust_type(ttype) - << "::try_from(" - << tvalue->get_integer() - << ").expect(\"expecting valid const value\")" - << endl; + f_gen_ << indent() << to_rust_type(ttype) << "::try_from(" << tvalue->get_integer() + << ").expect(\"expecting valid const value\")" << endl; indent_down(); f_gen_ << indent() << "}"; } else if (ttype->is_struct() || ttype->is_xception()) { @@ -780,7 +798,7 @@ void t_rs_generator::render_const_list(t_type* ttype, t_const_value* tvalue) { indent_up(); const vector& elems = tvalue->get_list(); vector::const_iterator elem_iter; - for(elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { + for (elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { f_gen_ << indent(); t_const_value* elem_value = (*elem_iter); render_const_value(elem_type, elem_value); @@ -796,7 +814,7 @@ void t_rs_generator::render_const_set(t_type* ttype, t_const_value* tvalue) { indent_up(); const vector& elems = tvalue->get_list(); vector::const_iterator elem_iter; - for(elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { + for (elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { f_gen_ << indent(); t_const_value* elem_value = (*elem_iter); render_const_value(elem_type, elem_value); @@ -811,7 +829,8 @@ void t_rs_generator::render_const_map(t_type* ttype, t_const_value* tvalue) { t_type* val_type = ((t_map*)ttype)->get_val_type(); f_gen_ << "BTreeMap::from([" << endl; indent_up(); - const map& elems = tvalue->get_map(); + const map& elems + = tvalue->get_map(); map::const_iterator elem_iter; for (elem_iter = elems.begin(); elem_iter != elems.end(); ++elem_iter) { t_const_value* key_value = elem_iter->first; @@ -840,7 +859,8 @@ void t_rs_generator::render_const_map(t_type* ttype, t_const_value* tvalue) { void t_rs_generator::generate_typedef(t_typedef* ttypedef) { std::string actual_type = to_rust_type(ttypedef->get_type()); - f_gen_ << "pub type " << rust_safe_name(ttypedef->get_symbolic()) << " = " << actual_type << ";" << endl; + f_gen_ << "pub type " << rust_safe_name(ttypedef->get_symbolic()) << " = " << actual_type << ";" + << endl; f_gen_ << endl; } @@ -858,7 +878,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); + render_rustdoc((t_doc*)tenum); f_gen_ << "#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]" << endl; f_gen_ << "pub struct " << enum_name << "(pub i32);" << endl; f_gen_ << endl; @@ -872,18 +892,14 @@ void t_rs_generator::render_enum_impl(t_enum* tenum, const string& enum_name) { // associated constants for each IDL-defined enum variant { - vector::iterator constants_iter; - for (constants_iter = constants.begin(); constants_iter != constants.end(); ++constants_iter) { - t_enum_value* val = (*constants_iter); - render_rustdoc((t_doc*) val); - f_gen_ - << indent() - << "pub const " << rust_enum_variant_name(val->get_name()) << ": " << enum_name - << " = " - << enum_name << "(" << val->get_value() << ")" - << ";" - << endl; - } + vector::iterator constants_iter; + for (constants_iter = constants.begin(); constants_iter != constants.end(); ++constants_iter) { + t_enum_value* val = (*constants_iter); + render_rustdoc((t_doc*)val); + f_gen_ << indent() << "pub const " << rust_enum_variant_name(val->get_name()) << ": " + << enum_name << " = " << enum_name << "(" << val->get_value() << ")" + << ";" << endl; + } } // array containing all IDL-defined enum variants @@ -893,11 +909,7 @@ void t_rs_generator::render_enum_impl(t_enum* tenum, const string& enum_name) { vector::iterator constants_iter; for (constants_iter = constants.begin(); constants_iter != constants.end(); ++constants_iter) { t_enum_value* val = (*constants_iter); - f_gen_ - << indent() - << "Self::" << rust_enum_variant_name(val->get_name()) - << "," - << endl; + f_gen_ << indent() << "Self::" << rust_enum_variant_name(val->get_name()) << "," << endl; } indent_down(); f_gen_ << indent() << "];" << endl; @@ -912,21 +924,21 @@ void t_rs_generator::render_enum_impl(t_enum* tenum, const string& enum_name) { f_gen_ << indent() << "#[allow(clippy::trivially_copy_pass_by_ref)]" << endl; f_gen_ - << indent() - << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" - << endl; + << indent() + << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" + << endl; indent_up(); f_gen_ << indent() << "o_prot.write_i32(self.0)" << endl; indent_down(); f_gen_ << indent() << "}" << endl; - f_gen_ - << indent() - << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" << enum_name << "> {" - << endl; + f_gen_ << indent() + << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" + << enum_name << "> {" << endl; indent_up(); f_gen_ << indent() << "let enum_value = i_prot.read_i32()?;" << endl; - f_gen_ << indent() << "Ok(" << enum_name << "::from(enum_value)" << ")" << endl; + f_gen_ << indent() << "Ok(" << enum_name << "::from(enum_value)" + << ")" << endl; indent_down(); f_gen_ << indent() << "}" << endl; @@ -947,11 +959,8 @@ void t_rs_generator::render_enum_conversion(t_enum* tenum, const string& enum_na vector::iterator constants_iter; for (constants_iter = constants.begin(); constants_iter != constants.end(); ++constants_iter) { t_enum_value* val = (*constants_iter); - f_gen_ - << indent() - << val->get_value() - << " => " << enum_name << "::" << rust_enum_variant_name(val->get_name()) << "," - << endl; + f_gen_ << indent() << val->get_value() << " => " << enum_name + << "::" << rust_enum_variant_name(val->get_name()) << "," << endl; } f_gen_ << indent() << "_ => " << enum_name << "(i)" << endl; indent_down(); @@ -1019,11 +1028,9 @@ void t_rs_generator::generate_struct(t_struct* tstruct) { } } -void t_rs_generator::render_struct( - const string& struct_name, - t_struct* tstruct, - t_rs_generator::e_struct_type struct_type -) { +void t_rs_generator::render_struct(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type) { render_type_comment(struct_name); render_struct_definition(struct_name, tstruct, struct_type); render_struct_impl(struct_name, tstruct, struct_type); @@ -1032,46 +1039,40 @@ void t_rs_generator::render_struct( } } -void t_rs_generator::render_struct_definition( - const string& struct_name, - t_struct* tstruct, - t_rs_generator::e_struct_type struct_type -) { - render_rustdoc((t_doc*) tstruct); +void t_rs_generator::render_struct_definition(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type) { + render_rustdoc((t_doc*)tstruct); const vector members = tstruct->get_sorted_members(); vector::const_iterator members_iter; - bool need_default = struct_type == t_rs_generator::T_REGULAR || struct_type == t_rs_generator::T_EXCEPTION; - for (members_iter = members.begin(); need_default && members_iter != members.end(); ++members_iter) { + bool need_default + = struct_type == t_rs_generator::T_REGULAR || struct_type == t_rs_generator::T_EXCEPTION; + for (members_iter = members.begin(); need_default && members_iter != members.end(); + ++members_iter) { t_field* member = *members_iter; if (!is_optional(member->get_req())) { need_default = false; } } - f_gen_ - << "#[derive(Clone, Debug" - << (need_default ? ", Default" : "") - << ", Eq, Hash, Ord, PartialEq, PartialOrd)]" - << endl; + f_gen_ << "#[derive(Clone, Debug" << (need_default ? ", Default" : "") + << ", Eq, Hash, Ord, PartialEq, PartialOrd)]" << endl; f_gen_ << visibility_qualifier(struct_type) << "struct " << struct_name << " {" << endl; // render the members if (!members.empty()) { indent_up(); - for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { + for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); string rust_type = to_rust_type(member->get_type()); rust_type = is_optional(member_req) ? "Option<" + rust_type + ">" : rust_type; - render_rustdoc((t_doc*) member); - f_gen_ - << indent() - << visibility_qualifier(struct_type) - << rust_field_name(member) << ": " << rust_type << "," - << endl; + render_rustdoc((t_doc*)member); + f_gen_ << indent() << visibility_qualifier(struct_type) << rust_field_name(member) << ": " + << rust_type << "," << endl; } indent_down(); @@ -1081,7 +1082,8 @@ void t_rs_generator::render_struct_definition( f_gen_ << endl; } -void t_rs_generator::render_exception_struct_error_trait_impls(const string& struct_name, t_struct* tstruct) { +void t_rs_generator::render_exception_struct_error_trait_impls(const string& struct_name, + t_struct* tstruct) { // error::Error trait f_gen_ << "impl Error for " << struct_name << " {}" << endl; f_gen_ << endl; @@ -1103,12 +1105,9 @@ void t_rs_generator::render_exception_struct_error_trait_impls(const string& str indent_up(); f_gen_ << indent() << "fn fmt(&self, f: &mut Formatter) -> fmt::Result {" << endl; indent_up(); - f_gen_ - << indent() - << "write!(f, " - << "\"remote service threw " << tstruct->get_name() << "\"" // use *original* name - << ")" - << endl; + f_gen_ << indent() << "write!(f, " + << "\"remote service threw " << tstruct->get_name() << "\"" // use *original* name + << ")" << endl; indent_down(); f_gen_ << indent() << "}" << endl; indent_down(); @@ -1116,11 +1115,9 @@ void t_rs_generator::render_exception_struct_error_trait_impls(const string& str f_gen_ << endl; } -void t_rs_generator::render_struct_impl( - const string& struct_name, - t_struct* tstruct, - t_rs_generator::e_struct_type struct_type -) { +void t_rs_generator::render_struct_impl(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type) { f_gen_ << "impl " << struct_name << " {" << endl; indent_up(); @@ -1149,21 +1146,19 @@ void t_rs_generator::render_struct_impl( f_gen_ << endl; } -void t_rs_generator::render_struct_constructor( - const string& struct_name, - t_struct* tstruct, - t_rs_generator::e_struct_type struct_type -) { +void t_rs_generator::render_struct_constructor(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type) { const vector& members = tstruct->get_sorted_members(); vector::const_iterator members_iter; - // build the convenience type parameters that allows us to pass unwrapped values to a constructor and - // have them automatically converted into Option + // build the convenience type parameters that allows us to pass unwrapped values to a constructor + // and have them automatically converted into Option bool first_arg = true; ostringstream generic_type_parameters; ostringstream generic_type_qualifiers; - for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { + for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); @@ -1175,7 +1170,8 @@ void t_rs_generator::render_struct_constructor( generic_type_qualifiers << ", "; } generic_type_parameters << "F" << rust_safe_field_id(member->get_key()); - generic_type_qualifiers << "F" << rust_safe_field_id(member->get_key()) << ": Intoget_type()) << ">>"; + generic_type_qualifiers << "F" << rust_safe_field_id(member->get_key()) << ": Intoget_type()) << ">>"; } } @@ -1190,11 +1186,11 @@ void t_rs_generator::render_struct_constructor( } // now build the actual constructor arg list - // when we're building this list we have to use the type parameters in place of the actual type names - // if necessary + // when we're building this list we have to use the type parameters in place of the actual type + // names if necessary ostringstream args; first_arg = true; - for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { + for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); string member_name(rust_field_name(member)); @@ -1206,7 +1202,8 @@ void t_rs_generator::render_struct_constructor( } if (is_optional(member_req)) { - args << member_name << ": " << "F" << rust_safe_field_id(member->get_key()); + args << member_name << ": " + << "F" << rust_safe_field_id(member->get_key()); } else { args << member_name << ": " << to_rust_type(member->get_type()); } @@ -1215,19 +1212,8 @@ void t_rs_generator::render_struct_constructor( string arg_string = args.str(); string visibility(visibility_qualifier(struct_type)); - f_gen_ - << indent() - << visibility - << "fn new" - << type_parameter_string - << "(" - << arg_string - << ") -> " - << struct_name - << " " - << type_qualifier_string - << "{" - << endl; + f_gen_ << indent() << visibility << "fn new" << type_parameter_string << "(" << arg_string + << ") -> " << struct_name << " " << type_qualifier_string << "{" << endl; indent_up(); if (members.empty()) { @@ -1236,7 +1222,7 @@ void t_rs_generator::render_struct_constructor( f_gen_ << indent() << struct_name << " {" << endl; indent_up(); - for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { + for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); string member_name(rust_field_name(member)); @@ -1265,7 +1251,7 @@ void t_rs_generator::render_result_struct_to_result_method(t_struct* tstruct) { if (index == std::string::npos) { throw "result struct " + service_call_name + " missing result suffix"; } else { - service_call_name.replace(index, 6, ""); + service_call_name.replace(index, 6, ""); } const vector& members = tstruct->get_sorted_members(); @@ -1273,7 +1259,7 @@ void t_rs_generator::render_result_struct_to_result_method(t_struct* tstruct) { // find out what the call's expected return type was string rust_return_type = "()"; - for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { + for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); if (member->get_name() == SERVICE_RESULT_VARIABLE) { // don't have to check safe name here rust_return_type = to_rust_type(member->get_type()); @@ -1292,7 +1278,7 @@ void t_rs_generator::render_result_struct_to_result_method(t_struct* tstruct) { int rendered_branch_count = 0; // render the exception branches - for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { + for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* tfield = (*members_iter); if (tfield->get_name() != SERVICE_RESULT_VARIABLE) { // don't have to check safe name here string field_name("self." + rust_field_name(tfield)); @@ -1300,7 +1286,8 @@ void t_rs_generator::render_result_struct_to_result_method(t_struct* tstruct) { f_gen_ << indent() << branch_statement << " " << field_name << ".is_some() {" << endl; indent_up(); - f_gen_ << indent() << "Err(thrift::Error::User(Box::new(" << field_name << ".unwrap())))" << endl; + f_gen_ << indent() << "Err(thrift::Error::User(Box::new(" << field_name << ".unwrap())))" + << endl; indent_down(); rendered_branch_count++; @@ -1324,7 +1311,8 @@ void t_rs_generator::render_result_struct_to_result_method(t_struct* tstruct) { } } else { string branch_statement = rendered_branch_count == 0 ? "if" : "} else if"; - f_gen_ << indent() << branch_statement << " self." << SERVICE_RESULT_VARIABLE << ".is_some() {" << endl; + f_gen_ << indent() << branch_statement << " self." << SERVICE_RESULT_VARIABLE << ".is_some() {" + << endl; indent_up(); f_gen_ << indent() << "Ok(self." << SERVICE_RESULT_VARIABLE << ".unwrap())" << endl; indent_down(); @@ -1332,12 +1320,8 @@ void t_rs_generator::render_result_struct_to_result_method(t_struct* tstruct) { indent_up(); // if we haven't found a valid return value *or* a user exception // then we're in trouble; return a default error - render_thrift_error( - "Application", - "ApplicationError", - "ApplicationErrorKind::MissingResult", - "\"no result received for " + service_call_name + "\"" - ); + render_thrift_error("Application", "ApplicationError", "ApplicationErrorKind::MissingResult", + "\"no result received for " + service_call_name + "\""); indent_down(); f_gen_ << indent() << "}" << endl; } @@ -1364,13 +1348,10 @@ void t_rs_generator::render_union_definition(const string& union_name, t_struct* indent_up(); vector::const_iterator member_iter; - for(member_iter = members.begin(); member_iter != members.end(); ++member_iter) { + for (member_iter = members.begin(); member_iter != members.end(); ++member_iter) { t_field* tfield = (*member_iter); - f_gen_ - << indent() - << rust_union_field_name(tfield) - << "(" << to_rust_type(tfield->get_type()) << ")," - << endl; + f_gen_ << indent() << rust_union_field_name(tfield) << "(" << to_rust_type(tfield->get_type()) + << ")," << endl; } indent_down(); @@ -1396,26 +1377,25 @@ void t_rs_generator::render_union_impl(const string& union_name, t_struct* tstru // //----------------------------------------------------------------------------- -void t_rs_generator::render_struct_sync_write( - t_struct *tstruct, - t_rs_generator::e_struct_type struct_type -) { +void t_rs_generator::render_struct_sync_write(t_struct* tstruct, + t_rs_generator::e_struct_type struct_type) { f_gen_ - << indent() - << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" - << endl; + << indent() + << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" + << endl; indent_up(); // write struct header to output protocol // note: use the *original* struct name here - f_gen_ << indent() << "let struct_ident = TStructIdentifier::new(\"" + tstruct->get_name() + "\");" << endl; + f_gen_ << indent() + << "let struct_ident = TStructIdentifier::new(\"" + tstruct->get_name() + "\");" << endl; f_gen_ << indent() << "o_prot.write_struct_begin(&struct_ident)?;" << endl; // write struct members to output protocol vector members = tstruct->get_sorted_members(); if (!members.empty()) { vector::iterator members_iter; - for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { + for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); string member_var("self." + rust_field_name(member)); @@ -1431,16 +1411,17 @@ void t_rs_generator::render_struct_sync_write( f_gen_ << indent() << "}" << endl; } -void t_rs_generator::render_union_sync_write(const string &union_name, t_struct *tstruct) { +void t_rs_generator::render_union_sync_write(const string& union_name, t_struct* tstruct) { f_gen_ - << indent() - << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" - << endl; + << indent() + << "fn write_to_out_protocol(&self, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" + << endl; indent_up(); // write struct header to output protocol // note: use the *original* struct name here - f_gen_ << indent() << "let struct_ident = TStructIdentifier::new(\"" + tstruct->get_name() + "\");" << endl; + f_gen_ << indent() + << "let struct_ident = TStructIdentifier::new(\"" + tstruct->get_name() + "\");" << endl; f_gen_ << indent() << "o_prot.write_struct_begin(&struct_ident)?;" << endl; // write the enum field to the output protocol @@ -1449,7 +1430,7 @@ void t_rs_generator::render_union_sync_write(const string &union_name, t_struct f_gen_ << indent() << "match *self {" << endl; indent_up(); vector::iterator members_iter; - for(members_iter = members.begin(); members_iter != members.end(); ++members_iter) { + for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* member = (*members_iter); t_field::e_req member_req = t_field::T_REQUIRED; t_type* ttype = member->get_type(); @@ -1458,11 +1439,8 @@ void t_rs_generator::render_union_sync_write(const string &union_name, t_struct ttype = ((t_typedef*)ttype)->get_type(); } string match_var((ttype->is_base_type() && !ttype->is_string()) ? "f" : "ref f"); - f_gen_ - << indent() - << union_name << "::" << rust_union_field_name(member) - << "(" << match_var << ") => {" - << endl; + f_gen_ << indent() << union_name << "::" << rust_union_field_name(member) << "(" << match_var + << ") => {" << endl; indent_up(); render_struct_field_sync_write("f", true, member, member_req); indent_down(); @@ -1480,25 +1458,23 @@ void t_rs_generator::render_union_sync_write(const string &union_name, t_struct f_gen_ << indent() << "}" << endl; } -void t_rs_generator::render_struct_field_sync_write( - const string &field_var, - bool field_var_is_ref, - t_field *tfield, - t_field::e_req req -) { +void t_rs_generator::render_struct_field_sync_write(const string& field_var, + bool field_var_is_ref, + t_field* tfield, + t_field::e_req req) { t_type* field_type = tfield->get_type(); t_type* actual_type = get_true_type(field_type); ostringstream field_stream; - field_stream - << "TFieldIdentifier::new(" - << "\"" << tfield->get_name() << "\"" << ", " // note: use *original* name - << to_rust_field_type_enum(field_type) << ", " - << tfield->get_key() << ")"; + field_stream << "TFieldIdentifier::new(" + << "\"" << tfield->get_name() << "\"" + << ", " // note: use *original* name + << to_rust_field_type_enum(field_type) << ", " << tfield->get_key() << ")"; string field_ident_string = field_stream.str(); if (is_optional(req)) { - string let_var((actual_type->is_base_type() && !actual_type->is_string()) ? "fld_var" : "ref fld_var"); + string let_var((actual_type->is_base_type() && !actual_type->is_string()) ? "fld_var" + : "ref fld_var"); f_gen_ << indent() << "if let Some(" << let_var << ") = " << field_var << " {" << endl; indent_up(); f_gen_ << indent() << "o_prot.write_field_begin(&" << field_ident_string << ")?;" << endl; @@ -1519,7 +1495,9 @@ void t_rs_generator::render_struct_field_sync_write( } } -void t_rs_generator::render_type_sync_write(const string &type_var, bool type_var_is_ref, t_type *ttype) { +void t_rs_generator::render_type_sync_write(const string& type_var, + bool type_var_is_ref, + t_type* ttype) { if (ttype->is_base_type()) { t_base_type* tbase_type = (t_base_type*)ttype; switch (tbase_type->get_base()) { @@ -1534,6 +1512,9 @@ void t_rs_generator::render_type_sync_write(const string &type_var, bool type_va } return; } + case t_base_type::TYPE_UUID: + f_gen_ << indent() << "o_prot.write_uuid(&" + type_var + ")?;" << endl; + return; case t_base_type::TYPE_BOOL: f_gen_ << indent() << "o_prot.write_bool(" + type_var + ")?;" << endl; return; @@ -1556,37 +1537,36 @@ void t_rs_generator::render_type_sync_write(const string &type_var, bool type_va throw "compiler error: unhandled type"; } } else if (ttype->is_typedef()) { - t_typedef* ttypedef = (t_typedef*) ttype; + t_typedef* ttypedef = (t_typedef*)ttype; render_type_sync_write(type_var, type_var_is_ref, ttypedef->get_type()); return; } else if (ttype->is_enum() || ttype->is_struct() || ttype->is_xception()) { f_gen_ << indent() << type_var + ".write_to_out_protocol(o_prot)?;" << endl; return; } else if (ttype->is_map()) { - render_map_sync_write(type_var, type_var_is_ref, (t_map *) ttype); + render_map_sync_write(type_var, type_var_is_ref, (t_map*)ttype); return; } else if (ttype->is_set()) { - render_set_sync_write(type_var, type_var_is_ref, (t_set *) ttype); + render_set_sync_write(type_var, type_var_is_ref, (t_set*)ttype); return; } else if (ttype->is_list()) { - render_list_sync_write(type_var, type_var_is_ref, (t_list *) ttype); + render_list_sync_write(type_var, type_var_is_ref, (t_list*)ttype); return; } throw "cannot write unsupported type " + ttype->get_name(); } -void t_rs_generator::render_list_sync_write(const string &list_var, bool list_var_is_ref, t_list *tlist) { +void t_rs_generator::render_list_sync_write(const string& list_var, + bool list_var_is_ref, + t_list* tlist) { t_type* elem_type = tlist->get_elem_type(); - f_gen_ - << indent() - << "o_prot.write_list_begin(" - << "&TListIdentifier::new(" - << to_rust_field_type_enum(elem_type) << ", " - << list_var << ".len() as i32" << ")" - << ")?;" - << endl; + f_gen_ << indent() << "o_prot.write_list_begin(" + << "&TListIdentifier::new(" << to_rust_field_type_enum(elem_type) << ", " << list_var + << ".len() as i32" + << ")" + << ")?;" << endl; string ref(list_var_is_ref ? "" : "&"); f_gen_ << indent() << "for e in " << ref << list_var << " {" << endl; @@ -1597,17 +1577,16 @@ void t_rs_generator::render_list_sync_write(const string &list_var, bool list_va f_gen_ << indent() << "o_prot.write_list_end()?;" << endl; } -void t_rs_generator::render_set_sync_write(const string &set_var, bool set_var_is_ref, t_set *tset) { +void t_rs_generator::render_set_sync_write(const string& set_var, + bool set_var_is_ref, + t_set* tset) { t_type* elem_type = tset->get_elem_type(); - f_gen_ - << indent() - << "o_prot.write_set_begin(" - << "&TSetIdentifier::new(" - << to_rust_field_type_enum(elem_type) << ", " - << set_var << ".len() as i32" << ")" - << ")?;" - << endl; + f_gen_ << indent() << "o_prot.write_set_begin(" + << "&TSetIdentifier::new(" << to_rust_field_type_enum(elem_type) << ", " << set_var + << ".len() as i32" + << ")" + << ")?;" << endl; string ref(set_var_is_ref ? "" : "&"); f_gen_ << indent() << "for e in " << ref << set_var << " {" << endl; @@ -1618,19 +1597,16 @@ void t_rs_generator::render_set_sync_write(const string &set_var, bool set_var_i f_gen_ << indent() << "o_prot.write_set_end()?;" << endl; } -void t_rs_generator::render_map_sync_write(const string &map_var, bool map_var_is_ref, t_map *tmap) { +void t_rs_generator::render_map_sync_write(const string& map_var, + bool map_var_is_ref, + t_map* tmap) { t_type* key_type = tmap->get_key_type(); t_type* val_type = tmap->get_val_type(); - f_gen_ - << indent() - << "o_prot.write_map_begin(" - << "&TMapIdentifier::new(" - << to_rust_field_type_enum(key_type) << ", " - << to_rust_field_type_enum(val_type) << ", " - << map_var << ".len() as i32)" - << ")?;" - << endl; + f_gen_ << indent() << "o_prot.write_map_begin(" + << "&TMapIdentifier::new(" << to_rust_field_type_enum(key_type) << ", " + << to_rust_field_type_enum(val_type) << ", " << map_var << ".len() as i32)" + << ")?;" << endl; string ref(map_var_is_ref ? "" : "&"); f_gen_ << indent() << "for (k, v) in " << ref << map_var << " {" << endl; @@ -1670,14 +1646,12 @@ bool t_rs_generator::needs_deref_on_container_write(t_type* ttype) { // //----------------------------------------------------------------------------- -void t_rs_generator::render_struct_sync_read( - const string &struct_name, - t_struct *tstruct, t_rs_generator::e_struct_type struct_type -) { - f_gen_ - << indent() - << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" << struct_name << "> {" - << endl; +void t_rs_generator::render_struct_sync_read(const string& struct_name, + t_struct* tstruct, + t_rs_generator::e_struct_type struct_type) { + f_gen_ << indent() + << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" + << struct_name << "> {" << endl; indent_up(); @@ -1690,16 +1664,14 @@ void t_rs_generator::render_struct_sync_read( t_field* member = (*members_iter); t_field::e_req member_req = actual_field_req(member, struct_type); - f_gen_ - << indent() - << "let mut " << struct_field_read_temp_variable(member) - << ": Option<" << to_rust_type(member->get_type()) << "> = "; - if (member_req == t_field::T_OPT_IN_REQ_OUT) { - f_gen_ << opt_in_req_out_value(member->get_type()) << ";"; - } else { - f_gen_ << "None;"; - } - f_gen_ << endl; + f_gen_ << indent() << "let mut " << struct_field_read_temp_variable(member) << ": Option<" + << to_rust_type(member->get_type()) << "> = "; + if (member_req == t_field::T_OPT_IN_REQ_OUT) { + f_gen_ << opt_in_req_out_value(member->get_type()) << ";"; + } else { + f_gen_ << "None;"; + } + f_gen_ << endl; } // now loop through the fields we've received @@ -1746,7 +1718,7 @@ void t_rs_generator::render_struct_sync_read( f_gen_ << indent() << "i_prot.read_field_end()?;" << endl; indent_down(); - f_gen_ << indent() << "}" << endl; // finish loop + f_gen_ << indent() << "}" << endl; // finish loop f_gen_ << indent() << "i_prot.read_struct_end()?;" << endl; // read message footer from the wire // verify that all required fields exist @@ -1754,13 +1726,10 @@ void t_rs_generator::render_struct_sync_read( t_field* tfield = (*members_iter); t_field::e_req req = actual_field_req(tfield, struct_type); if (!is_optional(req)) { - f_gen_ - << indent() - << "verify_required_field_exists(" - << "\"" << struct_name << "." << rust_field_name(tfield) << "\"" - << ", " - << "&" << struct_field_read_temp_variable(tfield) - << ")?;" << endl; + f_gen_ << indent() << "verify_required_field_exists(" + << "\"" << struct_name << "." << rust_field_name(tfield) << "\"" + << ", " + << "&" << struct_field_read_temp_variable(tfield) << ")?;" << endl; } } @@ -1779,14 +1748,10 @@ void t_rs_generator::render_struct_sync_read( if (is_optional(req)) { f_gen_ << indent() << field_name << ": " << field_key << "," << endl; } else { - f_gen_ - << indent() - << field_name - << ": " - << field_key - << ".expect(\"auto-generated code should have checked for presence of required fields\")" - << "," - << endl; + f_gen_ << indent() << field_name << ": " << field_key + << ".expect(\"auto-generated code should have checked for presence of required " + "fields\")" + << "," << endl; } } @@ -1801,11 +1766,10 @@ void t_rs_generator::render_struct_sync_read( f_gen_ << indent() << "}" << endl; } -void t_rs_generator::render_union_sync_read(const string &union_name, t_struct *tstruct) { - f_gen_ - << indent() - << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" << union_name << "> {" - << endl; +void t_rs_generator::render_union_sync_read(const string& union_name, t_struct* tstruct) { + f_gen_ << indent() + << "fn read_from_in_protocol(i_prot: &mut dyn TInputProtocol) -> thrift::Result<" + << union_name << "> {" << endl; indent_up(); // create temporary variables to hold the @@ -1842,10 +1806,8 @@ void t_rs_generator::render_union_sync_read(const string &union_name, t_struct * render_type_sync_read("val", member->get_type()); f_gen_ << indent() << "if ret.is_none() {" << endl; indent_up(); - f_gen_ - << indent() - << "ret = Some(" << union_name << "::" << rust_union_field_name(member) << "(val));" - << endl; + f_gen_ << indent() << "ret = Some(" << union_name << "::" << rust_union_field_name(member) + << "(val));" << endl; indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << indent() << "received_field_count += 1;" << endl; @@ -1865,27 +1827,19 @@ void t_rs_generator::render_union_sync_read(const string &union_name, t_struct * f_gen_ << indent() << "};" << endl; // finish match f_gen_ << indent() << "i_prot.read_field_end()?;" << endl; indent_down(); - f_gen_ << indent() << "}" << endl; // finish loop + f_gen_ << indent() << "}" << endl; // finish loop f_gen_ << indent() << "i_prot.read_struct_end()?;" << endl; // finish reading message from wire // return the value or an error f_gen_ << indent() << "if received_field_count == 0 {" << endl; indent_up(); - render_thrift_error( - "Protocol", - "ProtocolError", - "ProtocolErrorKind::InvalidData", - "\"received empty union from remote " + union_name + "\"" - ); + render_thrift_error("Protocol", "ProtocolError", "ProtocolErrorKind::InvalidData", + "\"received empty union from remote " + union_name + "\""); indent_down(); f_gen_ << indent() << "} else if received_field_count > 1 {" << endl; indent_up(); - render_thrift_error( - "Protocol", - "ProtocolError", - "ProtocolErrorKind::InvalidData", - "\"received multiple fields for union from remote " + union_name + "\"" - ); + render_thrift_error("Protocol", "ProtocolError", "ProtocolErrorKind::InvalidData", + "\"received multiple fields for union from remote " + union_name + "\""); indent_down(); f_gen_ << indent() << "} else {" << endl; indent_up(); @@ -1898,7 +1852,7 @@ void t_rs_generator::render_union_sync_read(const string &union_name, t_struct * } // Construct the rust representation of all supported types from the wire. -void t_rs_generator::render_type_sync_read(const string &type_var, t_type *ttype, bool is_boxed) { +void t_rs_generator::render_type_sync_read(const string& type_var, t_type* ttype, bool is_boxed) { if (ttype->is_base_type()) { t_base_type* tbase_type = (t_base_type*)ttype; switch (tbase_type->get_base()) { @@ -1911,6 +1865,9 @@ void t_rs_generator::render_type_sync_read(const string &type_var, t_type *ttype f_gen_ << indent() << "let " << type_var << " = i_prot.read_string()?;" << endl; } return; + case t_base_type::TYPE_UUID: + f_gen_ << indent() << "let " << type_var << " = i_prot.read_uuid()?;" << endl; + return; case t_base_type::TYPE_BOOL: f_gen_ << indent() << "let " << type_var << " = i_prot.read_bool()?;" << endl; return; @@ -1927,7 +1884,8 @@ void t_rs_generator::render_type_sync_read(const string &type_var, t_type *ttype f_gen_ << indent() << "let " << type_var << " = i_prot.read_i64()?;" << endl; return; case t_base_type::TYPE_DOUBLE: - f_gen_ << indent() << "let " << type_var << " = OrderedFloat::from(i_prot.read_double()?);" << endl; + f_gen_ << indent() << "let " << type_var << " = OrderedFloat::from(i_prot.read_double()?);" + << endl; return; default: throw "compiler error: unhandled type"; @@ -1947,19 +1905,16 @@ void t_rs_generator::render_type_sync_read(const string &type_var, t_type *ttype } else if (ttype->is_enum() || ttype->is_struct() || ttype->is_xception()) { string read_call(to_rust_type(ttype) + "::read_from_in_protocol(i_prot)?"); read_call = is_boxed ? "Box::new(" + read_call + ")" : read_call; - f_gen_ - << indent() - << "let " << type_var << " = " << read_call << ";" - << endl; + f_gen_ << indent() << "let " << type_var << " = " << read_call << ";" << endl; return; } else if (ttype->is_map()) { - render_map_sync_read((t_map *) ttype, type_var); + render_map_sync_read((t_map*)ttype, type_var); return; } else if (ttype->is_set()) { - render_set_sync_read((t_set *) ttype, type_var); + render_set_sync_read((t_set*)ttype, type_var); return; } else if (ttype->is_list()) { - render_list_sync_read((t_list *) ttype, type_var); + render_list_sync_read((t_list*)ttype, type_var); return; } @@ -1967,15 +1922,12 @@ void t_rs_generator::render_type_sync_read(const string &type_var, t_type *ttype } // Construct the rust representation of a list from the wire. -void t_rs_generator::render_list_sync_read(t_list *tlist, const string &list_var) { +void t_rs_generator::render_list_sync_read(t_list* tlist, const string& list_var) { t_type* elem_type = tlist->get_elem_type(); f_gen_ << indent() << "let list_ident = i_prot.read_list_begin()?;" << endl; - f_gen_ - << indent() - << "let mut " << list_var << ": " << to_rust_type((t_type*) tlist) - << " = Vec::with_capacity(list_ident.size as usize);" - << endl; + f_gen_ << indent() << "let mut " << list_var << ": " << to_rust_type((t_type*)tlist) + << " = Vec::with_capacity(list_ident.size as usize);" << endl; f_gen_ << indent() << "for _ in 0..list_ident.size {" << endl; indent_up(); @@ -1991,15 +1943,12 @@ void t_rs_generator::render_list_sync_read(t_list *tlist, const string &list_var } // Construct the rust representation of a set from the wire. -void t_rs_generator::render_set_sync_read(t_set *tset, const string &set_var) { +void t_rs_generator::render_set_sync_read(t_set* tset, const string& set_var) { t_type* elem_type = tset->get_elem_type(); f_gen_ << indent() << "let set_ident = i_prot.read_set_begin()?;" << endl; - f_gen_ - << indent() - << "let mut " << set_var << ": " << to_rust_type((t_type*) tset) - << " = BTreeSet::new();" - << endl; + f_gen_ << indent() << "let mut " << set_var << ": " << to_rust_type((t_type*)tset) + << " = BTreeSet::new();" << endl; f_gen_ << indent() << "for _ in 0..set_ident.size {" << endl; indent_up(); @@ -2015,16 +1964,13 @@ void t_rs_generator::render_set_sync_read(t_set *tset, const string &set_var) { } // Construct the rust representation of a map from the wire. -void t_rs_generator::render_map_sync_read(t_map *tmap, const string &map_var) { +void t_rs_generator::render_map_sync_read(t_map* tmap, const string& map_var) { t_type* key_type = tmap->get_key_type(); t_type* val_type = tmap->get_val_type(); f_gen_ << indent() << "let map_ident = i_prot.read_map_begin()?;" << endl; - f_gen_ - << indent() - << "let mut " << map_var << ": " << to_rust_type((t_type*) tmap) - << " = BTreeMap::new();" - << endl; + f_gen_ << indent() << "let mut " << map_var << ": " << to_rust_type((t_type*)tmap) + << " = BTreeMap::new();" << endl; f_gen_ << indent() << "for _ in 0..map_ident.size {" << endl; indent_up(); @@ -2033,7 +1979,8 @@ void t_rs_generator::render_map_sync_read(t_map *tmap, const string &map_var) { render_type_sync_read(key_elem_var, key_type); string val_elem_var = tmp("map_val_"); render_type_sync_read(val_elem_var, val_type); - f_gen_ << indent() << map_var << ".insert(" << key_elem_var << ", " << val_elem_var << ");" << endl; + f_gen_ << indent() << map_var << ".insert(" << key_elem_var << ", " << val_elem_var << ");" + << endl; indent_down(); @@ -2071,7 +2018,7 @@ void t_rs_generator::render_service_call_structs(t_service* tservice) { // that's passed over the wire, so, generate the struct // for that too. Note that this result struct *also* // contains the exceptions as well - for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { + for (func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); render_service_call_args_struct(tfunc); if (!tfunc->is_oneway()) { @@ -2088,30 +2035,32 @@ void t_rs_generator::render_sync_client(t_service* tservice) { render_sync_client_marker_trait(tservice); render_sync_client_definition_and_impl(client_impl_name); render_sync_client_tthriftclient_impl(client_impl_name); - render_sync_client_marker_trait_impls(tservice, client_impl_name); f_gen_ << endl; + render_sync_client_marker_trait_impls(tservice, client_impl_name); + f_gen_ << endl; render_sync_client_process_impl(tservice); } -void t_rs_generator::render_sync_client_trait(t_service *tservice) { +void t_rs_generator::render_sync_client_trait(t_service* tservice) { string extension = ""; if (tservice->get_extends()) { t_service* extends = tservice->get_extends(); extension = " : " + rust_namespace(extends) + rust_sync_client_trait_name(extends); } - render_rustdoc((t_doc*) tservice); + render_rustdoc((t_doc*)tservice); f_gen_ << "pub trait " << rust_sync_client_trait_name(tservice) << extension << " {" << endl; indent_up(); const std::vector functions = tservice->get_functions(); std::vector::const_iterator func_iter; - for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { + for (func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); string func_name = service_call_client_function_name(tfunc); string func_args = rust_sync_service_call_declaration(tfunc, true); string func_return = to_rust_type(tfunc->get_returntype()); - render_rustdoc((t_doc*) tfunc); - f_gen_ << indent() << "fn " << func_name << func_args << " -> thrift::Result<" << func_return << ">;" << endl; + render_rustdoc((t_doc*)tfunc); + f_gen_ << indent() << "fn " << func_name << func_args << " -> thrift::Result<" << func_return + << ">;" << endl; } indent_down(); @@ -2119,24 +2068,17 @@ void t_rs_generator::render_sync_client_trait(t_service *tservice) { f_gen_ << endl; } -void t_rs_generator::render_sync_client_marker_trait(t_service *tservice) { - f_gen_ << indent() << "pub trait " << rust_sync_client_marker_trait_name(tservice) << " {}" << endl; +void t_rs_generator::render_sync_client_marker_trait(t_service* tservice) { + f_gen_ << indent() << "pub trait " << rust_sync_client_marker_trait_name(tservice) << " {}" + << endl; f_gen_ << endl; } -void t_rs_generator::render_sync_client_marker_trait_impls(t_service *tservice, const string &impl_struct_name) { - f_gen_ - << indent() - << "impl " - << SYNC_CLIENT_GENERIC_BOUND_VARS - << " " - << rust_namespace(tservice) << rust_sync_client_marker_trait_name(tservice) - << " for " - << impl_struct_name << SYNC_CLIENT_GENERIC_BOUND_VARS - << " " - << SYNC_CLIENT_GENERIC_BOUNDS - << " {}" - << endl; +void t_rs_generator::render_sync_client_marker_trait_impls(t_service* tservice, + const string& impl_struct_name) { + f_gen_ << indent() << "impl " << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << rust_namespace(tservice) + << rust_sync_client_marker_trait_name(tservice) << " for " << impl_struct_name + << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << SYNC_CLIENT_GENERIC_BOUNDS << " {}" << endl; t_service* extends = tservice->get_extends(); if (extends) { @@ -2147,14 +2089,8 @@ void t_rs_generator::render_sync_client_marker_trait_impls(t_service *tservice, void t_rs_generator::render_sync_client_definition_and_impl(const string& client_impl_name) { // render the definition for the client struct - f_gen_ - << "pub struct " - << client_impl_name - << SYNC_CLIENT_GENERIC_BOUND_VARS - << " " - << SYNC_CLIENT_GENERIC_BOUNDS - << " {" - << endl; + f_gen_ << "pub struct " << client_impl_name << SYNC_CLIENT_GENERIC_BOUND_VARS << " " + << SYNC_CLIENT_GENERIC_BOUNDS << " {" << endl; indent_up(); f_gen_ << indent() << "_i_prot: IP," << endl; f_gen_ << indent() << "_o_prot: OP," << endl; @@ -2165,16 +2101,8 @@ void t_rs_generator::render_sync_client_definition_and_impl(const string& client // render the struct implementation // this includes the new() function as well as the helper send/recv methods for each service call - f_gen_ - << "impl " - << SYNC_CLIENT_GENERIC_BOUND_VARS - << " " - << client_impl_name - << SYNC_CLIENT_GENERIC_BOUND_VARS - << " " - << SYNC_CLIENT_GENERIC_BOUNDS - << " {" - << endl; + f_gen_ << "impl " << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << client_impl_name + << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << SYNC_CLIENT_GENERIC_BOUNDS << " {" << endl; indent_up(); render_sync_client_lifecycle_functions(client_impl_name); indent_down(); @@ -2183,45 +2111,32 @@ void t_rs_generator::render_sync_client_definition_and_impl(const string& client } void t_rs_generator::render_sync_client_lifecycle_functions(const string& client_struct) { - f_gen_ - << indent() - << "pub fn new(input_protocol: IP, output_protocol: OP) -> " - << client_struct - << SYNC_CLIENT_GENERIC_BOUND_VARS - << " {" - << endl; + f_gen_ << indent() << "pub fn new(input_protocol: IP, output_protocol: OP) -> " << client_struct + << SYNC_CLIENT_GENERIC_BOUND_VARS << " {" << endl; indent_up(); - f_gen_ - << indent() - << client_struct - << " { _i_prot: input_protocol, _o_prot: output_protocol, _sequence_number: 0 }" - << endl; + f_gen_ << indent() << client_struct + << " { _i_prot: input_protocol, _o_prot: output_protocol, _sequence_number: 0 }" << endl; indent_down(); f_gen_ << indent() << "}" << endl; } -void t_rs_generator::render_sync_client_tthriftclient_impl(const string &client_impl_name) { - f_gen_ - << indent() - << "impl " - << SYNC_CLIENT_GENERIC_BOUND_VARS - << " TThriftClient for " - << client_impl_name - << SYNC_CLIENT_GENERIC_BOUND_VARS - << " " - << SYNC_CLIENT_GENERIC_BOUNDS - << " {" << endl; - indent_up(); - - f_gen_ << indent() << "fn i_prot_mut(&mut self) -> &mut dyn TInputProtocol { &mut self._i_prot }" << endl; - f_gen_ << indent() << "fn o_prot_mut(&mut self) -> &mut dyn TOutputProtocol { &mut self._o_prot }" << endl; +void t_rs_generator::render_sync_client_tthriftclient_impl(const string& client_impl_name) { + f_gen_ << indent() << "impl " << SYNC_CLIENT_GENERIC_BOUND_VARS << " TThriftClient for " + << client_impl_name << SYNC_CLIENT_GENERIC_BOUND_VARS << " " << SYNC_CLIENT_GENERIC_BOUNDS + << " {" << endl; + indent_up(); + + f_gen_ << indent() << "fn i_prot_mut(&mut self) -> &mut dyn TInputProtocol { &mut self._i_prot }" + << endl; + f_gen_ << indent() << "fn o_prot_mut(&mut self) -> &mut dyn TOutputProtocol { &mut self._o_prot }" + << endl; f_gen_ << indent() << "fn sequence_number(&self) -> i32 { self._sequence_number }" << endl; - f_gen_ - << indent() - << "fn increment_sequence_number(&mut self) -> i32 { self._sequence_number += 1; self._sequence_number }" - << endl; + f_gen_ << indent() + << "fn increment_sequence_number(&mut self) -> i32 { self._sequence_number += 1; " + "self._sequence_number }" + << endl; indent_down(); f_gen_ << indent() << "}" << endl; @@ -2231,15 +2146,13 @@ void t_rs_generator::render_sync_client_tthriftclient_impl(const string &client_ void t_rs_generator::render_sync_client_process_impl(t_service* tservice) { string marker_extension = "" + sync_client_marker_traits_for_extension(tservice); - f_gen_ - << "impl " - << rust_sync_client_trait_name(tservice) - << " for C {" << endl; + f_gen_ << "impl " << rust_sync_client_trait_name(tservice) << " for C {" << endl; indent_up(); const std::vector functions = tservice->get_functions(); std::vector::const_iterator func_iter; - for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { + for (func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* func = (*func_iter); render_sync_send_recv_wrapper(func); } @@ -2249,12 +2162,13 @@ void t_rs_generator::render_sync_client_process_impl(t_service* tservice) { f_gen_ << endl; } -string t_rs_generator::sync_client_marker_traits_for_extension(t_service *tservice) { +string t_rs_generator::sync_client_marker_traits_for_extension(t_service* tservice) { string marker_extension; t_service* extends = tservice->get_extends(); if (extends) { - marker_extension = " + " + rust_namespace(extends) + rust_sync_client_marker_trait_name(extends); + marker_extension + = " + " + rust_namespace(extends) + rust_sync_client_marker_trait_name(extends); marker_extension = marker_extension + sync_client_marker_traits_for_extension(extends); } @@ -2267,11 +2181,8 @@ void t_rs_generator::render_sync_send_recv_wrapper(t_function* tfunc) { string func_call_args = rust_sync_service_call_invocation(tfunc); string func_return = to_rust_type(tfunc->get_returntype()); - f_gen_ - << indent() - << "fn " << func_name << func_decl_args << " -> thrift::Result<" << func_return - << "> {" - << endl; + f_gen_ << indent() << "fn " << func_name << func_decl_args << " -> thrift::Result<" << func_return + << "> {" << endl; indent_up(); f_gen_ << indent() << "(" << endl; @@ -2296,13 +2207,10 @@ void t_rs_generator::render_sync_send(t_function* tfunc) { // increment the sequence number and generate the call header string message_type = tfunc->is_oneway() ? "TMessageType::OneWay" : "TMessageType::Call"; f_gen_ << indent() << "self.increment_sequence_number();" << endl; - f_gen_ - << indent() - << "let message_ident = " - << "TMessageIdentifier::new(\"" << tfunc->get_name() << "\", " // note: use *original* name - << message_type << ", " - << "self.sequence_number());" - << endl; + f_gen_ << indent() << "let message_ident = " + << "TMessageIdentifier::new(\"" << tfunc->get_name() << "\", " // note: use *original* name + << message_type << ", " + << "self.sequence_number());" << endl; // pack the arguments into the containing struct that we'll write out over the wire // note that this struct is generated even if we have 0 args ostringstream struct_definition; @@ -2317,17 +2225,12 @@ void t_rs_generator::render_sync_send(t_function* tfunc) { if (struct_fields.size() > 0) { struct_fields = struct_fields.substr(0, struct_fields.size() - 2); // strip trailing comma } - f_gen_ - << indent() - << "let call_args = " - << service_call_args_struct_name(tfunc) - << " { " - << struct_fields - << " };" - << endl; + f_gen_ << indent() << "let call_args = " << service_call_args_struct_name(tfunc) << " { " + << struct_fields << " };" << endl; // write everything over the wire f_gen_ << indent() << "self.o_prot_mut().write_message_begin(&message_ident)?;" << endl; - f_gen_ << indent() << "call_args.write_to_out_protocol(self.o_prot_mut())?;" << endl; // written even if we have 0 args + f_gen_ << indent() << "call_args.write_to_out_protocol(self.o_prot_mut())?;" + << endl; // written even if we have 0 args f_gen_ << indent() << "self.o_prot_mut().write_message_end()?;" << endl; f_gen_ << indent() << "self.o_prot_mut().flush()" << endl; @@ -2340,18 +2243,28 @@ void t_rs_generator::render_sync_recv(t_function* tfunc) { indent_up(); f_gen_ << indent() << "let message_ident = self.i_prot_mut().read_message_begin()?;" << endl; - f_gen_ << indent() << "verify_expected_sequence_number(self.sequence_number(), message_ident.sequence_number)?;" << endl; - f_gen_ << indent() << "verify_expected_service_call(\"" << tfunc->get_name() <<"\", &message_ident.name)?;" << endl; // note: use *original* name + f_gen_ + << indent() + << "verify_expected_sequence_number(self.sequence_number(), message_ident.sequence_number)?;" + << endl; + f_gen_ << indent() << "verify_expected_service_call(\"" << tfunc->get_name() + << "\", &message_ident.name)?;" << endl; // note: use *original* name // FIXME: replace with a "try" block f_gen_ << indent() << "if message_ident.message_type == TMessageType::Exception {" << endl; indent_up(); - f_gen_ << indent() << "let remote_error = thrift::Error::read_application_error_from_in_protocol(self.i_prot_mut())?;" << endl; + f_gen_ << indent() + << "let remote_error = " + "thrift::Error::read_application_error_from_in_protocol(self.i_prot_mut())?;" + << endl; f_gen_ << indent() << "self.i_prot_mut().read_message_end()?;" << endl; f_gen_ << indent() << "return Err(thrift::Error::Application(remote_error))" << endl; indent_down(); f_gen_ << indent() << "}" << endl; - f_gen_ << indent() << "verify_expected_message_type(TMessageType::Reply, message_ident.message_type)?;" << endl; - f_gen_ << indent() << "let result = " << service_call_result_struct_name(tfunc) << "::read_from_in_protocol(self.i_prot_mut())?;" << endl; + f_gen_ << indent() + << "verify_expected_message_type(TMessageType::Reply, message_ident.message_type)?;" + << endl; + f_gen_ << indent() << "let result = " << service_call_result_struct_name(tfunc) + << "::read_from_in_protocol(self.i_prot_mut())?;" << endl; f_gen_ << indent() << "self.i_prot_mut().read_message_end()?;" << endl; f_gen_ << indent() << "result.ok_or()" << endl; @@ -2377,7 +2290,8 @@ string t_rs_generator::rust_sync_service_call_declaration(t_function* tfunc, boo return func_args.str(); } -string t_rs_generator::rust_sync_service_call_invocation(t_function* tfunc, const string& field_prefix) { +string t_rs_generator::rust_sync_service_call_invocation(t_function* tfunc, + const string& field_prefix) { ostringstream func_args; func_args << "("; @@ -2389,7 +2303,8 @@ string t_rs_generator::rust_sync_service_call_invocation(t_function* tfunc, cons return func_args.str(); } -string t_rs_generator::struct_to_declaration(t_struct* tstruct, t_rs_generator::e_struct_type struct_type) { +string t_rs_generator::struct_to_declaration(t_struct* tstruct, + t_rs_generator::e_struct_type struct_type) { ostringstream args; bool first_arg = true; @@ -2435,8 +2350,8 @@ string t_rs_generator::struct_to_invocation(t_struct* tstruct, const string& fie } void t_rs_generator::render_service_call_args_struct(t_function* tfunc) { - string args_struct_name(service_call_args_struct_name(tfunc)); - render_struct(args_struct_name, tfunc->get_arglist(), t_rs_generator::T_ARGS); + string args_struct_name(service_call_args_struct_name(tfunc)); + render_struct(args_struct_name, tfunc->get_arglist(), t_rs_generator::T_ARGS); } void t_rs_generator::render_service_call_result_value_struct(t_function* tfunc) { @@ -2452,7 +2367,8 @@ void t_rs_generator::render_service_call_result_value_struct(t_function* tfunc) t_struct* exceptions = tfunc->get_xceptions(); const vector& exception_types = exceptions->get_members(); vector::const_iterator exception_iter; - for(exception_iter = exception_types.begin(); exception_iter != exception_types.end(); ++exception_iter) { + for (exception_iter = exception_types.begin(); exception_iter != exception_types.end(); + ++exception_iter) { t_field* exception_type = *exception_iter; exception_type->set_req(t_field::T_OPTIONAL); result.append(exception_type); @@ -2467,13 +2383,13 @@ void t_rs_generator::render_service_call_result_value_struct(t_function* tfunc) // //----------------------------------------------------------------------------- -void t_rs_generator::render_sync_processor(t_service *tservice) { +void t_rs_generator::render_sync_processor(t_service* tservice) { render_type_comment(tservice->get_name() + " service processor"); // note: use *original* name render_sync_handler_trait(tservice); render_sync_processor_definition_and_impl(tservice); } -void t_rs_generator::render_sync_handler_trait(t_service *tservice) { +void t_rs_generator::render_sync_handler_trait(t_service* tservice) { string extension = ""; if (tservice->get_extends() != nullptr) { t_service* extends = tservice->get_extends(); @@ -2483,38 +2399,30 @@ void t_rs_generator::render_sync_handler_trait(t_service *tservice) { const std::vector functions = tservice->get_functions(); std::vector::const_iterator func_iter; - render_rustdoc((t_doc*) tservice); + render_rustdoc((t_doc*)tservice); f_gen_ << "pub trait " << rust_sync_handler_trait_name(tservice) << extension << " {" << endl; indent_up(); - for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { + for (func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); string func_name = service_call_handler_function_name(tfunc); string func_args = rust_sync_service_call_declaration(tfunc, false); string func_return = to_rust_type(tfunc->get_returntype()); - render_rustdoc((t_doc*) tfunc); - f_gen_ - << indent() - << "fn " - << func_name << func_args - << " -> thrift::Result<" << func_return << ">;" - << endl; + render_rustdoc((t_doc*)tfunc); + f_gen_ << indent() << "fn " << func_name << func_args << " -> thrift::Result<" << func_return + << ">;" << endl; } indent_down(); f_gen_ << indent() << "}" << endl; f_gen_ << endl; } -void t_rs_generator::render_sync_processor_definition_and_impl(t_service *tservice) { +void t_rs_generator::render_sync_processor_definition_and_impl(t_service* tservice) { string service_processor_name = rust_sync_processor_name(tservice); string handler_trait_name = rust_sync_handler_trait_name(tservice); // struct - f_gen_ - << indent() - << "pub struct " << service_processor_name - << " {" - << endl; + f_gen_ << indent() << "pub struct " << service_processor_name << " {" << endl; indent_up(); f_gen_ << indent() << "handler: H," << endl; indent_down(); @@ -2522,12 +2430,8 @@ void t_rs_generator::render_sync_processor_definition_and_impl(t_service *tservi f_gen_ << endl; // delegating impl - f_gen_ - << indent() - << "impl " - << service_processor_name - << " {" - << endl; + f_gen_ << indent() << "impl " << service_processor_name + << " {" << endl; indent_up(); f_gen_ << indent() << "pub fn new(handler: H) -> " << service_processor_name << " {" << endl; indent_up(); @@ -2552,7 +2456,7 @@ void t_rs_generator::render_sync_processor_definition_and_impl(t_service *tservi vector functions = tservice->get_functions(); vector::iterator func_iter; - for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { + for (func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); render_sync_process_function(tfunc, handler_trait_name); } @@ -2562,40 +2466,33 @@ void t_rs_generator::render_sync_processor_definition_and_impl(t_service *tservi f_gen_ << endl; // processor impl - f_gen_ - << indent() - << "impl TProcessor for " - << service_processor_name - << " {" - << endl; + f_gen_ << indent() << "impl TProcessor for " + << service_processor_name << " {" << endl; indent_up(); - f_gen_ - << indent() - << "fn process(&self, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol) -> thrift::Result<()> {" - << endl; + f_gen_ << indent() + << "fn process(&self, i_prot: &mut dyn TInputProtocol, o_prot: &mut dyn TOutputProtocol) " + "-> thrift::Result<()> {" + << endl; indent_up(); f_gen_ << indent() << "let message_ident = i_prot.read_message_begin()?;" << endl; - f_gen_ << indent() << "let res = match &*message_ident.name {" << endl; // [sigh] explicit deref coercion + f_gen_ << indent() << "let res = match &*message_ident.name {" + << endl; // [sigh] explicit deref coercion indent_up(); render_process_match_statements(tservice); f_gen_ << indent() << "method => {" << endl; indent_up(); - render_thrift_error( - "Application", - "ApplicationError", - "ApplicationErrorKind::UnknownMethod", - "format!(\"unknown method {}\", method)" - ); + render_thrift_error("Application", "ApplicationError", "ApplicationErrorKind::UnknownMethod", + "format!(\"unknown method {}\", method)"); indent_down(); f_gen_ << indent() << "}," << endl; indent_down(); f_gen_ << indent() << "};" << endl; - f_gen_ << indent() << "thrift::server::handle_process_result(&message_ident, res, o_prot)" << endl; + f_gen_ << indent() << "thrift::server::handle_process_result(&message_ident, res, o_prot)" + << endl; indent_down(); f_gen_ << indent() << "}" << endl; @@ -2605,36 +2502,27 @@ void t_rs_generator::render_sync_processor_definition_and_impl(t_service *tservi f_gen_ << endl; } -void t_rs_generator::render_sync_process_delegation_functions(t_service *tservice) { +void t_rs_generator::render_sync_process_delegation_functions(t_service* tservice) { string actual_processor(rust_namespace(tservice) + rust_sync_processor_impl_name(tservice)); vector functions = tservice->get_functions(); vector::iterator func_iter; - for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { + for (func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); string function_name("process_" + rust_snake_case(tfunc->get_name())); - f_gen_ - << indent() - << "fn " << function_name - << "(&self, " - << "incoming_sequence_number: i32, " - << "i_prot: &mut dyn TInputProtocol, " - << "o_prot: &mut dyn TOutputProtocol) " - << "-> thrift::Result<()> {" - << endl; + f_gen_ << indent() << "fn " << function_name << "(&self, " + << "incoming_sequence_number: i32, " + << "i_prot: &mut dyn TInputProtocol, " + << "o_prot: &mut dyn TOutputProtocol) " + << "-> thrift::Result<()> {" << endl; indent_up(); - f_gen_ - << indent() - << actual_processor - << "::" << function_name - << "(" - << "&self.handler, " - << "incoming_sequence_number, " - << "i_prot, " - << "o_prot" - << ")" - << endl; + f_gen_ << indent() << actual_processor << "::" << function_name << "(" + << "&self.handler, " + << "incoming_sequence_number, " + << "i_prot, " + << "o_prot" + << ")" << endl; indent_down(); f_gen_ << indent() << "}" << endl; @@ -2649,15 +2537,13 @@ void t_rs_generator::render_sync_process_delegation_functions(t_service *tservic void t_rs_generator::render_process_match_statements(t_service* tservice) { vector functions = tservice->get_functions(); vector::iterator func_iter; - for(func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { + for (func_iter = functions.begin(); func_iter != functions.end(); ++func_iter) { t_function* tfunc = (*func_iter); - f_gen_ << indent() << "\"" << tfunc->get_name() << "\"" << " => {" << endl; // note: use *original* name + f_gen_ << indent() << "\"" << tfunc->get_name() << "\"" + << " => {" << endl; // note: use *original* name indent_up(); - f_gen_ - << indent() - << "self.process_" << rust_snake_case(tfunc->get_name()) - << "(message_ident.sequence_number, i_prot, o_prot)" - << endl; + f_gen_ << indent() << "self.process_" << rust_snake_case(tfunc->get_name()) + << "(message_ident.sequence_number, i_prot, o_prot)" << endl; indent_down(); f_gen_ << indent() << "}," << endl; } @@ -2668,7 +2554,7 @@ void t_rs_generator::render_process_match_statements(t_service* tservice) { } } -void t_rs_generator::render_sync_process_function(t_function *tfunc, const string &handler_type) { +void t_rs_generator::render_sync_process_function(t_function* tfunc, const string& handler_type) { string sequence_number_param("incoming_sequence_number"); string output_protocol_param("o_prot"); @@ -2677,40 +2563,26 @@ void t_rs_generator::render_sync_process_function(t_function *tfunc, const strin output_protocol_param = "_"; } - f_gen_ - << indent() - << "pub fn process_" << rust_snake_case(tfunc->get_name()) - << "" - << "(handler: &H, " - << sequence_number_param << ": i32, " - << "i_prot: &mut dyn TInputProtocol, " - << output_protocol_param << ": &mut dyn TOutputProtocol) " - << "-> thrift::Result<()> {" - << endl; + f_gen_ << indent() << "pub fn process_" << rust_snake_case(tfunc->get_name()) + << "" + << "(handler: &H, " << sequence_number_param << ": i32, " + << "i_prot: &mut dyn TInputProtocol, " << output_protocol_param + << ": &mut dyn TOutputProtocol) " + << "-> thrift::Result<()> {" << endl; indent_up(); // *always* read arguments from the input protocol - f_gen_ - << indent() - << "let " - << (has_non_void_args(tfunc) ? "args" : "_") - << " = " - << service_call_args_struct_name(tfunc) - << "::read_from_in_protocol(i_prot)?;" - << endl; + f_gen_ << indent() << "let " << (has_non_void_args(tfunc) ? "args" : "_") << " = " + << service_call_args_struct_name(tfunc) << "::read_from_in_protocol(i_prot)?;" << endl; - f_gen_ - << indent() - << "match handler." - << service_call_handler_function_name(tfunc) - << rust_sync_service_call_invocation(tfunc, "args.") - << " {" - << endl; // start match + f_gen_ << indent() << "match handler." << service_call_handler_function_name(tfunc) + << rust_sync_service_call_invocation(tfunc, "args.") << " {" << endl; // start match indent_up(); // handler succeeded - string handler_return_variable = tfunc->is_oneway() || tfunc->get_returntype()->is_void() ? "_" : "handler_return"; + string handler_return_variable + = tfunc->is_oneway() || tfunc->get_returntype()->is_void() ? "_" : "handler_return"; f_gen_ << indent() << "Ok(" << handler_return_variable << ") => {" << endl; indent_up(); render_sync_handler_succeeded(tfunc); @@ -2730,33 +2602,31 @@ void t_rs_generator::render_sync_process_function(t_function *tfunc, const strin f_gen_ << indent() << "}" << endl; // end function } -void t_rs_generator::render_sync_handler_succeeded(t_function *tfunc) { +void t_rs_generator::render_sync_handler_succeeded(t_function* tfunc) { if (tfunc->is_oneway()) { f_gen_ << indent() << "Ok(())" << endl; } else { - f_gen_ - << indent() - << "let message_ident = TMessageIdentifier::new(" - << "\"" << tfunc->get_name() << "\", " // note: use *original* name - << "TMessageType::Reply, " - << "incoming_sequence_number);" - << endl; + f_gen_ << indent() << "let message_ident = TMessageIdentifier::new(" + << "\"" << tfunc->get_name() << "\", " // note: use *original* name + << "TMessageType::Reply, " + << "incoming_sequence_number);" << endl; f_gen_ << indent() << "o_prot.write_message_begin(&message_ident)?;" << endl; - f_gen_ << indent() << "let ret = " << handler_successful_return_struct(tfunc) <<";" << endl; + f_gen_ << indent() << "let ret = " << handler_successful_return_struct(tfunc) << ";" << endl; f_gen_ << indent() << "ret.write_to_out_protocol(o_prot)?;" << endl; f_gen_ << indent() << "o_prot.write_message_end()?;" << endl; f_gen_ << indent() << "o_prot.flush()" << endl; } } -void t_rs_generator::render_sync_handler_failed(t_function *tfunc) { +void t_rs_generator::render_sync_handler_failed(t_function* tfunc) { string err_var("e"); f_gen_ << indent() << "match " << err_var << " {" << endl; indent_up(); // if there are any user-defined exceptions for this service call handle them first - if (tfunc->get_xceptions() != nullptr && tfunc->get_xceptions()->get_sorted_members().size() > 0) { + if (tfunc->get_xceptions() != nullptr + && tfunc->get_xceptions()->get_sorted_members().size() > 0) { string user_err_var("usr_err"); f_gen_ << indent() << "thrift::Error::User(" << user_err_var << ") => {" << endl; indent_up(); @@ -2784,7 +2654,7 @@ void t_rs_generator::render_sync_handler_failed(t_function *tfunc) { f_gen_ << indent() << "}" << endl; } -void t_rs_generator::render_sync_handler_failed_user_exception_branch(t_function *tfunc) { +void t_rs_generator::render_sync_handler_failed_user_exception_branch(t_function* tfunc) { if (tfunc->get_xceptions() == nullptr || tfunc->get_xceptions()->get_sorted_members().empty()) { throw "cannot render user exception branches if no user exceptions defined"; } @@ -2799,13 +2669,12 @@ void t_rs_generator::render_sync_handler_failed_user_exception_branch(t_function string if_statement(branches_rendered == 0 ? "if usr_err" : "} else if usr_err"); string exception_type(to_rust_type(xception_field->get_type())); - f_gen_ << indent() << if_statement << ".downcast_ref::<" << exception_type << ">().is_some() {" << endl; + f_gen_ << indent() << if_statement << ".downcast_ref::<" << exception_type << ">().is_some() {" + << endl; indent_up(); - f_gen_ - << indent() - << "let err = usr_err.downcast::<" << exception_type << ">().expect(\"downcast already checked\");" - << endl; + f_gen_ << indent() << "let err = usr_err.downcast::<" << exception_type + << ">().expect(\"downcast already checked\");" << endl; // render the members of the return struct ostringstream members; @@ -2816,7 +2685,8 @@ void t_rs_generator::render_sync_handler_failed_user_exception_branch(t_function } vector::const_iterator xception_members_iter; - for(xception_members_iter = txceptions.begin(); xception_members_iter != txceptions.end(); ++xception_members_iter) { + for (xception_members_iter = txceptions.begin(); xception_members_iter != txceptions.end(); + ++xception_members_iter) { t_field* member = (*xception_members_iter); string member_name(rust_field_name(member)); if (member == xception_field) { @@ -2830,21 +2700,14 @@ void t_rs_generator::render_sync_handler_failed_user_exception_branch(t_function member_string.replace(member_string.size() - 2, 2, " "); // trim trailing comma // now write out the return struct - f_gen_ - << indent() - << "let ret_err = " - << service_call_result_struct_name(tfunc) - << "{ " << member_string << "};" - << endl; - - f_gen_ - << indent() - << "let message_ident = " - << "TMessageIdentifier::new(" - << "\"" << tfunc->get_name() << "\", " // note: use *original* name - << "TMessageType::Reply, " - << "incoming_sequence_number);" - << endl; + f_gen_ << indent() << "let ret_err = " << service_call_result_struct_name(tfunc) << "{ " + << member_string << "};" << endl; + + f_gen_ << indent() << "let message_ident = " + << "TMessageIdentifier::new(" + << "\"" << tfunc->get_name() << "\", " // note: use *original* name + << "TMessageType::Reply, " + << "incoming_sequence_number);" << endl; f_gen_ << indent() << "o_prot.write_message_begin(&message_ident)?;" << endl; f_gen_ << indent() << "ret_err.write_to_out_protocol(o_prot)?;" << endl; f_gen_ << indent() << "o_prot.write_message_end()?;" << endl; @@ -2863,7 +2726,8 @@ void t_rs_generator::render_sync_handler_failed_user_exception_branch(t_function f_gen_ << indent() << "let ret_err = {" << endl; indent_up(); - render_thrift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", "usr_err.to_string()"); + render_thrift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", + "usr_err.to_string()"); indent_down(); f_gen_ << indent() << "};" << endl; render_sync_handler_send_exception_response(tfunc, "ret_err"); @@ -2873,9 +2737,8 @@ void t_rs_generator::render_sync_handler_failed_user_exception_branch(t_function } void t_rs_generator::render_sync_handler_failed_application_exception_branch( - t_function *tfunc, - const string &app_err_var -) { + t_function* tfunc, + const string& app_err_var) { if (tfunc->is_oneway()) { f_gen_ << indent() << "Err(thrift::Error::Application(" << app_err_var << "))" << endl; } else { @@ -2883,7 +2746,7 @@ void t_rs_generator::render_sync_handler_failed_application_exception_branch( } } -void t_rs_generator::render_sync_handler_failed_default_exception_branch(t_function *tfunc) { +void t_rs_generator::render_sync_handler_failed_default_exception_branch(t_function* tfunc) { f_gen_ << indent() << "let ret_err = {" << endl; indent_up(); render_thrift_error_struct("ApplicationError", "ApplicationErrorKind::Unknown", "e.to_string()"); @@ -2896,16 +2759,15 @@ void t_rs_generator::render_sync_handler_failed_default_exception_branch(t_funct } } -void t_rs_generator::render_sync_handler_send_exception_response(t_function *tfunc, const string &err_var) { - f_gen_ - << indent() - << "let message_ident = TMessageIdentifier::new(" - << "\"" << tfunc->get_name() << "\", " // note: use *original* name - << "TMessageType::Exception, " - << "incoming_sequence_number);" - << endl; +void t_rs_generator::render_sync_handler_send_exception_response(t_function* tfunc, + const string& err_var) { + f_gen_ << indent() << "let message_ident = TMessageIdentifier::new(" + << "\"" << tfunc->get_name() << "\", " // note: use *original* name + << "TMessageType::Exception, " + << "incoming_sequence_number);" << endl; f_gen_ << indent() << "o_prot.write_message_begin(&message_ident)?;" << endl; - f_gen_ << indent() << "thrift::Error::write_application_error_to_out_protocol(&" << err_var << ", o_prot)?;" << endl; + f_gen_ << indent() << "thrift::Error::write_application_error_to_out_protocol(&" << err_var + << ", o_prot)?;" << endl; f_gen_ << indent() << "o_prot.write_message_end()?;" << endl; f_gen_ << indent() << "o_prot.flush()" << endl; } @@ -2929,7 +2791,9 @@ string t_rs_generator::handler_successful_return_struct(t_function* tfunc) { vector::const_iterator members_iter; for (members_iter = members.begin(); members_iter != members.end(); ++members_iter) { t_field* xception_field = (*members_iter); - if (member_count > 0) { return_struct << ", "; } + if (member_count > 0) { + return_struct << ", "; + } return_struct << rust_field_name(xception_field) << ": None"; member_count++; } @@ -2937,7 +2801,7 @@ string t_rs_generator::handler_successful_return_struct(t_function* tfunc) { return_struct << " }"; - return return_struct.str(); + return return_struct.str(); } //----------------------------------------------------------------------------- @@ -2963,12 +2827,10 @@ void t_rs_generator::render_rustdoc(t_doc* tdoc) { generate_docstring_comment(f_gen_, "", "/// ", tdoc->get_doc(), ""); } -void t_rs_generator::render_thrift_error( - const string& error_kind, - const string& error_struct, - const string& sub_error_kind, - const string& error_message -) { +void t_rs_generator::render_thrift_error(const string& error_kind, + const string& error_struct, + const string& sub_error_kind, + const string& error_message) { f_gen_ << indent() << "Err(" << endl; indent_up(); f_gen_ << indent() << "thrift::Error::" << error_kind << "(" << endl; @@ -2980,11 +2842,9 @@ void t_rs_generator::render_thrift_error( f_gen_ << indent() << ")" << endl; } -void t_rs_generator::render_thrift_error_struct( - const string& error_struct, - const string& sub_error_kind, - const string& error_message -) { +void t_rs_generator::render_thrift_error_struct(const string& error_struct, + const string& sub_error_kind, + const string& error_message) { f_gen_ << indent() << error_struct << "::new(" << endl; indent_up(); f_gen_ << indent() << sub_error_kind << "," << endl; @@ -3018,6 +2878,8 @@ string t_rs_generator::to_rust_type(t_type* ttype) { } else { return "String"; } + case t_base_type::TYPE_UUID: + return "uuid::Uuid"; case t_base_type::TYPE_BOOL: return "bool"; case t_base_type::TYPE_I8: @@ -3036,7 +2898,7 @@ string t_rs_generator::to_rust_type(t_type* ttype) { } else if (ttype->is_typedef()) { t_typedef* ttypedef = (t_typedef*)ttype; string rust_type = rust_namespace(ttype) + ttypedef->get_symbolic(); - rust_type = ttypedef->is_forward_typedef() ? "Box<" + rust_type + ">" : rust_type; + rust_type = ttypedef->is_forward_typedef() ? "Box<" + rust_type + ">" : rust_type; return rust_type; } else if (ttype->is_enum()) { return rust_namespace(ttype) + rust_camel_case(ttype->get_name()); @@ -3044,7 +2906,8 @@ string t_rs_generator::to_rust_type(t_type* ttype) { return rust_namespace(ttype) + rust_camel_case(ttype->get_name()); } else if (ttype->is_map()) { t_map* tmap = (t_map*)ttype; - return "BTreeMap<" + to_rust_type(tmap->get_key_type()) + ", " + to_rust_type(tmap->get_val_type()) + ">"; + return "BTreeMap<" + to_rust_type(tmap->get_key_type()) + ", " + + to_rust_type(tmap->get_val_type()) + ">"; } else if (ttype->is_set()) { t_set* tset = (t_set*)ttype; return "BTreeSet<" + to_rust_type(tset->get_elem_type()) + ">"; @@ -3080,6 +2943,8 @@ string t_rs_generator::to_rust_field_type_enum(t_type* ttype) { throw "will not generate protocol::TType for TYPE_VOID"; case t_base_type::TYPE_STRING: // both strings and binary are actually encoded as TType::String return "TType::String"; + case t_base_type::TYPE_UUID: + return "TType::Uuid"; case t_base_type::TYPE_BOOL: return "TType::Bool"; case t_base_type::TYPE_I8: @@ -3123,6 +2988,8 @@ string t_rs_generator::opt_in_req_out_value(t_type* ttype) { } else { return "Some(\"\".to_owned())"; } + case t_base_type::TYPE_UUID: + return "Some(uuid::Uuid::nil())"; case t_base_type::TYPE_BOOL: return "Some(false)"; case t_base_type::TYPE_I8: @@ -3172,7 +3039,8 @@ bool t_rs_generator::is_optional(t_field::e_req req) { return req == t_field::T_OPTIONAL || req == t_field::T_OPT_IN_REQ_OUT; } -t_field::e_req t_rs_generator::actual_field_req(t_field* tfield, t_rs_generator::e_struct_type struct_type) { +t_field::e_req t_rs_generator::actual_field_req(t_field* tfield, + t_rs_generator::e_struct_type struct_type) { return struct_type == t_rs_generator::T_ARGS ? t_field::T_REQUIRED : tfield->get_req(); } @@ -3197,7 +3065,7 @@ bool t_rs_generator::has_non_void_args(t_function* tfunc) { } string t_rs_generator::visibility_qualifier(t_rs_generator::e_struct_type struct_type) { - switch(struct_type) { + switch (struct_type) { case t_rs_generator::T_ARGS: case t_rs_generator::T_RESULT: return ""; @@ -3286,11 +3154,11 @@ string t_rs_generator::rust_sync_processor_name(t_service* tservice) { return rust_camel_case(tservice->get_name()) + "SyncProcessor"; } -string t_rs_generator::rust_sync_processor_impl_name(t_service *tservice) { +string t_rs_generator::rust_sync_processor_impl_name(t_service* tservice) { return "T" + rust_camel_case(tservice->get_name()) + "ProcessFunctions"; } -string t_rs_generator::rust_enum_variant_name(const string &name) { +string t_rs_generator::rust_enum_variant_name(const string& name) { bool all_uppercase = true; for (char i : name) { @@ -3341,17 +3209,19 @@ string t_rs_generator::rust_camel_case(const string& name) { } string t_rs_generator::rust_safe_field_id(int32_t id) { - string id_str = std::to_string(abs(id)); - if (id >= 0) { - return id_str; - } else { - string str("neg"); - str += id_str; - return str; - } + string id_str = std::to_string(abs(id)); + if (id >= 0) { + return id_str; + } else { + string str("neg"); + str += id_str; + return str; + } } -void t_rs_generator::string_replace(string& target, const string& search_string, const string& replace_string) { +void t_rs_generator::string_replace(string& target, + const string& search_string, + const string& replace_string) { if (target.empty()) { return; } @@ -3371,8 +3241,4 @@ std::string t_rs_generator::display_name() const { return "Rust"; } - -THRIFT_REGISTER_GENERATOR( - rs, - "Rust", - "\n") // no Rust-generator-specific options +THRIFT_REGISTER_GENERATOR(rs, "Rust", "\n") // no Rust-generator-specific options diff --git a/lib/rs/Cargo.toml b/lib/rs/Cargo.toml index 38c277df5e..a6e8533aa5 100644 --- a/lib/rs/Cargo.toml +++ b/lib/rs/Cargo.toml @@ -15,6 +15,7 @@ keywords = ["thrift"] [dependencies] byteorder = "1.3" integer-encoding = "3.0.3" +uuid = "1" log = {version = "0.4", optional = true} ordered-float = "3.0" threadpool = {version = "1.7", optional = true} @@ -22,3 +23,6 @@ threadpool = {version = "1.7", optional = true} [features] default = ["server"] server = ["threadpool", "log"] + +[dev-dependencies] +uuid = { version = "*", features = ["v4"] } diff --git a/lib/rs/src/errors.rs b/lib/rs/src/errors.rs index fc263309d4..3cd77e573d 100644 --- a/lib/rs/src/errors.rs +++ b/lib/rs/src/errors.rs @@ -441,6 +441,15 @@ impl From for Error { } } +impl From for Error { + fn from(err: uuid::Error) -> Self { + Error::Protocol(ProtocolError { + kind: ProtocolErrorKind::InvalidData, + message: err.to_string(), // FIXME: use fmt::Error's debug string + }) + } +} + impl From for Error { fn from(err: string::FromUtf8Error) -> Self { Error::Protocol(ProtocolError { diff --git a/lib/rs/src/protocol/binary.rs b/lib/rs/src/protocol/binary.rs index 9f8af430ba..5da801807e 100644 --- a/lib/rs/src/protocol/binary.rs +++ b/lib/rs/src/protocol/binary.rs @@ -190,6 +190,14 @@ where self.transport.read_f64::().map_err(From::from) } + fn read_uuid(&mut self) -> crate::Result { + let mut buf = [0u8; 16]; + self.transport + .read_exact(&mut buf) + .map(|_| uuid::Uuid::from_bytes(buf)) + .map_err(From::from) + } + fn read_string(&mut self) -> crate::Result { let bytes = self.read_bytes()?; String::from_utf8(bytes).map_err(From::from) @@ -389,6 +397,12 @@ where self.write_bytes(s.as_bytes()) } + fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> { + self.transport + .write_all(uuid.as_bytes()) + .map_err(From::from) + } + fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> { self.write_byte(field_type_to_u8(identifier.element_type))?; self.write_i32(identifier.size) @@ -470,8 +484,7 @@ fn field_type_to_u8(field_type: TType) -> u8 { TType::Map => 0x0D, TType::Set => 0x0E, TType::List => 0x0F, - TType::Utf8 => 0x10, - TType::Utf16 => 0x11, + TType::Uuid => 0x10, } } @@ -490,8 +503,7 @@ fn field_type_from_u8(b: u8) -> crate::Result { 0x0D => Ok(TType::Map), 0x0E => Ok(TType::Set), 0x0F => Ok(TType::List), - 0x10 => Ok(TType::Utf8), - 0x11 => Ok(TType::Utf16), + 0x10 => Ok(TType::Uuid), unkn => Err(crate::Error::Protocol(ProtocolError { kind: ProtocolErrorKind::InvalidData, message: format!("cannot convert {} to TType", unkn), @@ -885,6 +897,25 @@ mod tests { assert_eq!(&buf[4..], bytes); // actual bytes } + #[test] + fn must_write_uuid() { + let (_, mut o_prot) = test_objects(true); + let uuid = uuid::Uuid::new_v4(); + assert!(o_prot.write_uuid(&uuid).is_ok()); + let buf = o_prot.transport.write_bytes(); + assert_eq!(&buf, uuid.as_bytes()); + } + + #[test] + fn must_round_trip_uuid() { + let (mut i_prot, mut o_prot) = test_objects(true); + let uuid = uuid::uuid!("F9168C5E-CEB2-4faa-B6BF-329BF39FA1E4"); + assert!(o_prot.write_uuid(&uuid).is_ok()); + copy_write_buffer_to_read_buffer!(o_prot); + let received_uuid = assert_success!(i_prot.read_uuid()); + assert_eq!(&received_uuid, &uuid); + } + #[test] fn must_round_trip_bytes() { let (mut i_prot, mut o_prot) = test_objects(true); diff --git a/lib/rs/src/protocol/compact.rs b/lib/rs/src/protocol/compact.rs index 87cfbfc46e..a1aa253293 100644 --- a/lib/rs/src/protocol/compact.rs +++ b/lib/rs/src/protocol/compact.rs @@ -252,6 +252,10 @@ where .map_err(From::from) } + fn read_uuid(&mut self) -> crate::Result { + uuid::Uuid::from_slice(&self.read_bytes()?).map_err(From::from) + } + fn read_string(&mut self) -> crate::Result { let bytes = self.read_bytes()?; String::from_utf8(bytes).map_err(From::from) @@ -538,6 +542,10 @@ where .map_err(From::from) } + fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> { + self.write_bytes(uuid.as_bytes()) + } + fn write_string(&mut self, s: &str) -> crate::Result<()> { self.write_bytes(s.as_bytes()) } @@ -637,6 +645,7 @@ fn type_to_u8(field_type: TType) -> u8 { TType::Set => 0x0A, TType::Map => 0x0B, TType::Struct => 0x0C, + TType::Uuid => 0x0D, _ => panic!("should not have attempted to convert {} to u8", field_type), } } @@ -661,6 +670,7 @@ fn u8_to_type(b: u8) -> crate::Result { 0x0A => Ok(TType::Set), 0x0B => Ok(TType::Map), 0x0C => Ok(TType::Struct), + 0x0D => Ok(TType::Uuid), unkn => Err(crate::Error::Protocol(crate::ProtocolError { kind: crate::ProtocolErrorKind::InvalidData, message: format!("cannot convert {} into TType", unkn), diff --git a/lib/rs/src/protocol/mod.rs b/lib/rs/src/protocol/mod.rs index 019f717212..0e47795d0b 100644 --- a/lib/rs/src/protocol/mod.rs +++ b/lib/rs/src/protocol/mod.rs @@ -171,6 +171,8 @@ pub trait TInputProtocol { fn read_i64(&mut self) -> crate::Result; /// Read a 64-bit float. fn read_double(&mut self) -> crate::Result; + /// Read a UUID. + fn read_uuid(&mut self) -> crate::Result; /// Read a fixed-length string (not null terminated). fn read_string(&mut self) -> crate::Result; /// Read the beginning of a list. @@ -323,6 +325,8 @@ pub trait TOutputProtocol { fn write_i64(&mut self, i: i64) -> crate::Result<()>; /// Write a 64-bit float. fn write_double(&mut self, d: f64) -> crate::Result<()>; + /// Write a UUID + fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()>; /// Write a fixed-length string. fn write_string(&mut self, s: &str) -> crate::Result<()>; /// Write the beginning of a list. @@ -405,6 +409,10 @@ where (**self).read_double() } + fn read_uuid(&mut self) -> crate::Result { + (**self).read_uuid() + } + fn read_string(&mut self) -> crate::Result { (**self).read_string() } @@ -498,6 +506,10 @@ where (**self).write_double(d) } + fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> { + (**self).write_uuid(uuid) + } + fn write_string(&mut self, s: &str) -> crate::Result<()> { (**self).write_string(s) } @@ -823,8 +835,8 @@ pub enum TType { List, /// UTF-8 string. Utf8, - /// UTF-16 string. *Unsupported*. - Utf16, + /// Uuid. + Uuid, } impl Display for TType { @@ -845,7 +857,7 @@ impl Display for TType { TType::Set => write!(f, "set"), TType::List => write!(f, "list"), TType::Utf8 => write!(f, "UTF8"), - TType::Utf16 => write!(f, "UTF16"), + TType::Uuid => write!(f, "UUID"), } } } diff --git a/lib/rs/src/protocol/multiplexed.rs b/lib/rs/src/protocol/multiplexed.rs index 697b7e6bce..48d49891fd 100644 --- a/lib/rs/src/protocol/multiplexed.rs +++ b/lib/rs/src/protocol/multiplexed.rs @@ -152,6 +152,10 @@ where self.inner.write_string(s) } + fn write_uuid(&mut self, uuid: &uuid::Uuid) -> crate::Result<()> { + self.inner.write_uuid(uuid) + } + fn write_list_begin(&mut self, identifier: &TListIdentifier) -> crate::Result<()> { self.inner.write_list_begin(identifier) } diff --git a/lib/rs/src/protocol/stored.rs b/lib/rs/src/protocol/stored.rs index 179ae07b00..f4bdfb1978 100644 --- a/lib/rs/src/protocol/stored.rs +++ b/lib/rs/src/protocol/stored.rs @@ -158,6 +158,10 @@ impl<'a> TInputProtocol for TStoredInputProtocol<'a> { self.inner.read_double() } + fn read_uuid(&mut self) -> crate::Result { + self.inner.read_uuid() + } + fn read_string(&mut self) -> crate::Result { self.inner.read_string() } diff --git a/lib/rs/test/Cargo.toml b/lib/rs/test/Cargo.toml index a1c6836da1..4c64f38f2e 100644 --- a/lib/rs/test/Cargo.toml +++ b/lib/rs/test/Cargo.toml @@ -10,6 +10,7 @@ publish = false clap = "~2.33" bitflags = "=1.2" log = "0.4" +uuid = "1" [dependencies.thrift] path = "../" diff --git a/lib/rs/test/thrifts/Base_One.thrift b/lib/rs/test/thrifts/Base_One.thrift index c5fa6c20df..f1214c909c 100644 --- a/lib/rs/test/thrifts/Base_One.thrift +++ b/lib/rs/test/thrifts/Base_One.thrift @@ -74,6 +74,7 @@ struct Recipe { 1: string recipeName 2: string cuisine 3: i8 page + 4: uuid recipeId } union CookingTools { diff --git a/test/rs/Cargo.toml b/test/rs/Cargo.toml index b039fff4c9..da53b967a0 100644 --- a/test/rs/Cargo.toml +++ b/test/rs/Cargo.toml @@ -11,7 +11,7 @@ clap = "~2.33" bitflags = "=1.2" env_logger = "0.8" log = "0.4" +uuid = "1" [dependencies.thrift] path = "../../lib/rs" - diff --git a/test/rs/Makefile.am b/test/rs/Makefile.am index 103f80c9ad..78db5ee0c5 100644 --- a/test/rs/Makefile.am +++ b/test/rs/Makefile.am @@ -17,8 +17,8 @@ # under the License. # -stubs: ../v0.16/ThriftTest.thrift - $(THRIFT) -I ./thrifts -out src --gen rs ../v0.16/ThriftTest.thrift +stubs: ../ThriftTest.thrift + $(THRIFT) -I ./thrifts -out src --gen rs ../ThriftTest.thrift precross: stubs $(CARGO) build diff --git a/test/rs/src/bin/test_client.rs b/test/rs/src/bin/test_client.rs index a44bac3c9c..fd3a18550b 100644 --- a/test/rs/src/bin/test_client.rs +++ b/test/rs/src/bin/test_client.rs @@ -231,6 +231,12 @@ fn make_thrift_calls( "thing".to_owned(), )?; + info!("testUuid"); + verify_expected_result( + thrift_test_client.test_uuid(uuid::uuid!("00010203-0405-0607-0809-0a0b0c0d0e0f")), + uuid::uuid!("00010203-0405-0607-0809-0a0b0c0d0e0f"), + )?; + info!("testBool"); verify_expected_result(thrift_test_client.test_bool(true), true)?; diff --git a/test/rs/src/bin/test_server.rs b/test/rs/src/bin/test_server.rs index 92a4bcc45b..3e622d5503 100644 --- a/test/rs/src/bin/test_server.rs +++ b/test/rs/src/bin/test_server.rs @@ -174,6 +174,11 @@ impl ThriftTestSyncHandler for ThriftTestSyncHandlerImpl { Ok(thing) } + fn handle_test_uuid(&self, thing: uuid::Uuid) -> thrift::Result { + info!("testUUID({})", &thing); + Ok(thing) + } + fn handle_test_bool(&self, thing: bool) -> thrift::Result { info!("testBool({})", thing); Ok(thing)