Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,12 @@ set(CMAKE_MODULE_PATH "${CMAKE_MODULE_PATH}" "${CMAKE_CURRENT_SOURCE_DIR}/build/
file (STRINGS "${CMAKE_CURRENT_SOURCE_DIR}/configure.ac" CONFIGURE_AC REGEX "AC_INIT\\(.*\\)" )

# The following variable is used in the version.h.in file
string(REGEX REPLACE "AC_INIT\\(\\[.*\\], \\[([0-9]+\\.[0-9]+\\.[0-9]+(-dev)?)\\]\\)" "\\1" PACKAGE_VERSION ${CONFIGURE_AC})
#string(REGEX REPLACE "AC_INIT\\(\\[.*\\], \\[([0-9]+\\.[0-9]+\\.[0-9]+(-dev)?)\\]\\)" "\\1" PACKAGE_VERSION ${CONFIGURE_AC})
string(REGEX REPLACE "AC_INIT\\(\\[.*\\], \\[([0-9]+\\.[0-9]+\\.[0-9]+(-dev)?(\\.[a-z0-9-]+)?)\\]\\)" "\\1" PACKAGE_VERSION ${CONFIGURE_AC})
message(STATUS "Parsed Thrift package version: ${PACKAGE_VERSION}")

# These are internal to CMake
string(REGEX REPLACE "([0-9]+\\.[0-9]+\\.[0-9]+)(-dev)?" "\\1" thrift_VERSION ${PACKAGE_VERSION})
string(REGEX REPLACE "([0-9]+\\.[0-9]+\\.[0-9]+)(-dev)?(\\.[a-z0-9-]+)" "\\1" thrift_VERSION ${PACKAGE_VERSION})
string(REGEX REPLACE "([0-9]+)\\.[0-9]+\\.[0-9]+" "\\1" thrift_VERSION_MAJOR ${thrift_VERSION})
string(REGEX REPLACE "[0-9]+\\.([0-9])+\\.[0-9]+" "\\1" thrift_VERSION_MINOR ${thrift_VERSION})
string(REGEX REPLACE "[0-9]+\\.[0-9]+\\.([0-9]+)" "\\1" thrift_VERSION_PATCH ${thrift_VERSION})
Expand Down
328 changes: 325 additions & 3 deletions compiler/cpp/src/generate/t_swift_generator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,14 @@ class t_swift_generator : public t_oop_generator {
void generate_swift_struct_result_writer(ofstream& out, t_struct* tstruct);
void generate_swift_struct_printable_extension(ofstream& out, t_struct* tstruct);

void generate_swift_union(ofstream& out, t_struct* tstruct);
void generate_swift_union_implementation(ofstream& out, t_struct* tstruct);
void generate_swift_union_equatable_extension(ofstream& out, t_struct* tstruct);
void generate_swift_union_hashable_extension(ofstream& out, t_struct* tstruct);
void generate_swift_union_thrift_extension(ofstream& out, t_struct* tstruct);
void generate_swift_union_reader(ofstream& out, t_struct* tstruct);
void generate_swift_union_writer(ofstream& out, t_struct* tstruct);

string function_result_helper_struct_type(t_service *tservice, t_function* tfunction);
string function_args_helper_struct_type(t_service* tservice, t_function* tfunction);
void generate_function_helpers(t_service *tservice, t_function* tfunction);
Expand Down Expand Up @@ -420,8 +428,13 @@ void t_swift_generator::generate_consts(vector<t_const*> consts) {
* @param tstruct The struct definition
*/
void t_swift_generator::generate_struct(t_struct* tstruct) {
generate_swift_struct(f_decl_, tstruct, false);
generate_swift_struct_implementation(f_impl_, tstruct, false, false);
if (tstruct->is_union()) {
generate_swift_union(f_decl_, tstruct);
generate_swift_union_implementation(f_impl_, tstruct);
} else {
generate_swift_struct(f_decl_, tstruct, false);
generate_swift_struct_implementation(f_impl_, tstruct, false, false);
}
}

/**
Expand Down Expand Up @@ -572,7 +585,7 @@ void t_swift_generator::generate_swift_struct_hashable_extension(ofstream& out,
t_field* tfield = *m_iter;
string accessor = field_is_optional(tfield) ? "?." : ".";
string defaultor = field_is_optional(tfield) ? " ?? 0" : "";
indent(out) << "result = prime * result + (" << maybe_escape_identifier(tfield->get_name()) << accessor
indent(out) << "result = prime &* result &+ (" << maybe_escape_identifier(tfield->get_name()) << accessor
<< "hashValue" << defaultor << ")" << endl;
}

Expand Down Expand Up @@ -967,6 +980,315 @@ void t_swift_generator::generate_swift_struct_printable_extension(ofstream& out,
out << endl;
}

/**
* Generate the definition of a union.
*
* @param tstruct The struct definition
*/
void t_swift_generator::generate_swift_union(ofstream& out, t_struct* tstruct) {

indent(out) << "public indirect enum " << tstruct->get_name();

block_open(out);

// properties
const vector<t_field*>& members = tstruct->get_members();
vector<t_field*>::const_iterator m_iter;

for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_field* tfield = *m_iter;
out << endl;
indent(out) << "case " << maybe_escape_identifier(tfield->get_name())
<< "(" << type_name(tfield->get_type()) << ")" << endl;
}

// Add extra case for unknown values, needed for extensibility
// TODO: could make optional or give configurable name..
out << endl;
indent(out) << "case ThriftUnknownValue" << endl;

out << endl;

// Need default initializer to work with
indent(out) << "public init() { self = .ThriftUnknownValue }" << endl;

out << endl;

block_close(out);

out << endl;
}

/**
* Generate union implementation. Produces extensions that
* fulfill the requisite protocols to complete the value.
*
* @param tstruct The struct definition
*/
void t_swift_generator::generate_swift_union_implementation(ofstream& out, t_struct* tstruct) {

generate_swift_union_equatable_extension(out, tstruct);

generate_swift_union_hashable_extension(out, tstruct);
generate_swift_union_thrift_extension(out, tstruct);

out << endl << endl;
}

/**
* Generate the equatable protocol implementation for a union
*
* @param tstruct The structure definition
*/
void t_swift_generator::generate_swift_union_equatable_extension(ofstream& out, t_struct* tstruct) {

indent(out) << "public func ==(lhs: " << type_name(tstruct) << ", rhs: " << type_name(tstruct) << ") -> Bool";

block_open(out);

indent(out) << "switch (lhs, rhs)";

block_open(out);

const vector<t_field*>& members = tstruct->get_members();
vector<t_field*>::const_iterator m_iter;
for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_field* tfield = *m_iter;
indent(out) << "case "
<< "(." << maybe_escape_identifier(tfield->get_name()) << "(let a), "
<< "." << maybe_escape_identifier(tfield->get_name()) << "(let b)): "
<< "return a == b" << endl;
}

// Probably need this to avoid surprises
indent(out) << "case (.ThriftUnknownValue, .ThriftUnknownValue): return true" << endl;
indent(out) << "default: return false" << endl;

block_close(out);

block_close(out);

out << endl;
}

/**
* Generate the hashable protocol implementation for a union
*
* @param tstruct The structure definition
*/
void t_swift_generator::generate_swift_union_hashable_extension(ofstream& out, t_struct* tstruct) {

indent(out) << "extension " << tstruct->get_name() << " : Hashable";
block_open(out);

out << endl;

indent(out) << "public var hashValue : Int";
block_open(out);

const vector<t_field*>& members = tstruct->get_members();
vector<t_field*>::const_iterator m_iter;

indent(out) << "let prime = 31" << endl;

indent(out) << "switch self";
block_open(out);

string exponated_prime = "prime";

for (m_iter = members.begin(); m_iter != members.end(); ++m_iter) {
t_field* tfield = *m_iter;
indent(out) << "case ." << maybe_escape_identifier(tfield->get_name()) << "(let a): "
<< "return " << exponated_prime << " &+ a.hashValue" << endl;
exponated_prime += " &* prime";
}

indent(out) << "case .ThriftUnknownValue: "
<< "return " << exponated_prime << endl;

block_close(out);

block_close(out);

out << endl;

block_close(out);

out << endl;
}

/**
* Generate the TStruct protocol implementation for a union
*
* @param tstruct The structure definition
*/
void t_swift_generator::generate_swift_union_thrift_extension(ofstream& out, t_struct* tstruct) {

indent(out) << "extension " << tstruct->get_name() << " : TStruct";

block_open(out);

out << endl;

generate_swift_union_reader(out, tstruct);

generate_swift_union_writer(out, tstruct);

block_close(out);

out << endl;
}

/**
* Generates a function to read a union from
* from a protocol. (TStruct compliance)
*
* @param tstruct The structure definition
*/
void t_swift_generator::generate_swift_union_reader(ofstream& out, t_struct* tstruct) {

indent(out) << "public static func readValueFromProtocol(__proto: TProtocol) throws -> "
<< tstruct->get_name();

block_open(out);

out << endl;

indent(out) << "try __proto.readStructBegin()" << endl << endl;

indent(out) << "var __value : " << tstruct->get_name() << "!" << endl;

indent(out) << "let (_, fieldType, fieldID) = try __proto.readFieldBegin()" << endl << endl;

indent(out) << "switch (fieldID, fieldType)";
block_open(out);

// Union should contain exactly one value, if it contains less,
// signal a protol error
indent(out) << "case (_, .STOP):" << endl;
indent_up();
// TODO: will need to throw a better error here
indent(out) << "throw NSError(" << endl;
indent_up();
indent(out) << "domain: TProtocolErrorDomain," << endl;
indent(out) << "code: Int(TProtocolError.InvalidData.rawValue)," << endl;
indent(out) << "userInfo: [TProtocolErrorExtendedErrorKey: TProtocolExtendedError.MissingRequiredField.rawValue])" << endl << endl;
indent_down();
indent_down();

const vector<t_field*>& fields = tstruct->get_members();
vector<t_field*>::const_iterator f_iter;

// Generate deserialization code for known cases
for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {

indent(out) << "case (" << (*f_iter)->get_key() << ", " << type_to_enum((*f_iter)->get_type()) << "):" << endl;
indent_up();
indent(out) << "let __v = try __proto.readValue() as "
<< type_name((*f_iter)->get_type()) << endl;
indent(out) << "__value = ." << maybe_escape_identifier((*f_iter)->get_name()) << "(__v)" << endl << endl;
indent_down();
}

// Unknown value
indent(out) << "case let (_, unknownType):" << endl;
indent_up();
indent(out) << "try __proto.skipType(unknownType)" << endl;
indent(out) << "__value = .ThriftUnknownValue" << endl;
indent_down();

block_close(out);

indent(out) << "try __proto.readFieldEnd()" << endl;

// Try to read another field. We expect exactly one field, so the only valid value here is .STOP
indent(out) << "let (_, secondFieldType, secondFieldID) = try __proto.readFieldBegin()" << endl << endl;
indent(out) << "if secondFieldType != .STOP";
block_open(out);
// TODO: will need to throw a better error here
indent(out) << "throw NSError(" << endl;
indent_up();
indent(out) << "domain: TProtocolErrorDomain," << endl;
indent(out) << "code: Int(TProtocolError.InvalidData.rawValue)," << endl;
indent(out) << "userInfo: [TProtocolErrorExtendedErrorKey: secondFieldID])" << endl;
indent_down();
block_close(out);

indent(out) << "try __proto.readFieldEnd()" << endl;

out << endl;

indent(out) << "try __proto.readStructEnd()" << endl;

indent(out) << "return __value" << endl;

block_close(out);

out << endl;
}


/**
* Generates a function to write a union to
* a protocol. (TStruct compliance)
*
* @param tstruct The structure definition
*/
void t_swift_generator::generate_swift_union_writer(ofstream& out, t_struct* tstruct) {

indent(out) << "public static func writeValue(__value: " << tstruct->get_name() << ", toProtocol __proto: TProtocol) throws";

block_open(out);

out << endl;

const vector<t_field*>& fields = tstruct->get_members();
vector<t_field*>::const_iterator f_iter;

indent(out) << "try __proto.writeStructBeginWithName(\"" << tstruct->get_name() << "\")" << endl;

out << endl;

indent(out) << "switch __value";
block_open(out);

for (f_iter = fields.begin(); f_iter != fields.end(); ++f_iter) {
t_field *tfield = *f_iter;

indent(out) << "case ." << maybe_escape_identifier(tfield->get_name()) << "(let __v):" << endl;
indent_up();
indent(out) << "try __proto.writeFieldValue("
<< "__v" << ", "
<< "name: \"" << tfield->get_name() << "\", "
<< "type: " << type_to_enum(tfield->get_type()) << ", "
<< "id: " << tfield->get_key() << ")" << endl;
indent_down();

out << endl;
}

indent(out) << "case .ThriftUnknownValue:" << endl;
// TODO: Will need to throw a better error here
indent_up();
indent(out) << "throw NSError(" << endl;
indent_up();
indent(out) << "domain: TProtocolErrorDomain, " << endl;
indent(out) << "code: Int(TProtocolError.InvalidData.rawValue)," << endl;
indent(out) << "userInfo: [])" << endl;
indent_down();
indent_down();

block_close(out);

indent(out) << "try __proto.writeFieldStop()" << endl << endl;

indent(out) << "try __proto.writeStructEnd()" << endl;

block_close(out);

out << endl;
}

/**
* Generates a thrift service. In Swift this consists of a
* protocol definition and a client (with it's implementation
Expand Down
2 changes: 1 addition & 1 deletion configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
AC_PREREQ(2.65)
AC_CONFIG_MACRO_DIR([./aclocal])

AC_INIT([thrift], [1.0.0-dev])
AC_INIT([thrift], [1.0.0-dev.zedge-20160408.2])

AC_CONFIG_AUX_DIR([.])

Expand Down