SharedRefPtr<DataType> decode_user_type() { StringRef keyspace; buffer_ = decode_string(buffer_, &keyspace); StringRef type_name; buffer_ = decode_string(buffer_, &type_name); uint16_t n; buffer_ = decode_uint16(buffer_, n); UserType::FieldVec fields; for (uint16_t i = 0; i < n; ++i) { StringRef field_name; buffer_ = decode_string(buffer_, &field_name); fields.push_back(UserType::Field(field_name.to_string(), decode())); } return SharedRefPtr<DataType>(new UserType(keyspace.to_string(), type_name.to_string(), fields)); }
DataType::ConstPtr DataTypeClassNameParser::parse_one(const std::string& type, const NativeDataTypes& native_types) { bool is_frozen = DataTypeClassNameParser::is_frozen(type); std::string class_name; if (is_reversed(type) || is_frozen) { if (!get_nested_class_name(type, &class_name)) { return DataType::ConstPtr(); } } else { class_name = type; } Parser parser(class_name, 0); std::string next; parser.get_next_name(&next); if (starts_with(next, LIST_TYPE)) { TypeParamsVec params; if (!parser.get_type_params(¶ms) || params.empty()) { return DataType::ConstPtr(); } DataType::ConstPtr element_type(parse_one(params[0], native_types)); if (!element_type) { return DataType::ConstPtr(); } return CollectionType::list(element_type, is_frozen); } else if(starts_with(next, SET_TYPE)) { TypeParamsVec params; if (!parser.get_type_params(¶ms) || params.empty()) { return DataType::ConstPtr(); } DataType::ConstPtr element_type(parse_one(params[0], native_types)); if (!element_type) { return DataType::ConstPtr(); } return CollectionType::set(element_type, is_frozen); } else if(starts_with(next, MAP_TYPE)) { TypeParamsVec params; if (!parser.get_type_params(¶ms) || params.size() < 2) { return DataType::ConstPtr(); } DataType::ConstPtr key_type(parse_one(params[0], native_types)); DataType::ConstPtr value_type(parse_one(params[1], native_types)); if (!key_type || !value_type) { return DataType::ConstPtr(); } return CollectionType::map(key_type, value_type, is_frozen); } if (is_frozen) { LOG_WARN("Got a frozen type for something other than a collection, " "this driver might be too old for your version of Cassandra"); } if (is_user_type(next)) { parser.skip(); // Skip '(' std::string keyspace; if (!parser.read_one(&keyspace)) { return DataType::ConstPtr(); } parser.skip_blank_and_comma(); std::string hex; if (!parser.read_one(&hex)) { return DataType::ConstPtr(); } std::string type_name; if (!from_hex(hex, &type_name)) { LOG_ERROR("Invalid hex string \"%s\" for parameter", hex.c_str()); return DataType::ConstPtr(); } if (keyspace.empty() || type_name.empty()) { LOG_ERROR("UDT has no keyspace or type name"); return DataType::ConstPtr(); } parser.skip_blank_and_comma(); NameAndTypeParamsVec raw_fields; if (!parser.get_name_and_type_params(&raw_fields)) { return DataType::ConstPtr(); } UserType::FieldVec fields; for (NameAndTypeParamsVec::const_iterator i = raw_fields.begin(), end = raw_fields.end(); i != end; ++i) { DataType::ConstPtr data_type = parse_one(i->second, native_types); if (!data_type) { return DataType::ConstPtr(); } fields.push_back(UserType::Field(i->first, data_type)); } return DataType::ConstPtr(new UserType(keyspace, type_name, fields, true)); } if (is_tuple_type(type)) { TypeParamsVec raw_types; if (!parser.get_type_params(&raw_types)) { return DataType::ConstPtr(); } DataType::Vec types; for (TypeParamsVec::const_iterator i = raw_types.begin(), end = raw_types.end(); i != end; ++i) { DataType::ConstPtr data_type = parse_one(*i, native_types); if (!data_type) { return DataType::ConstPtr(); } types.push_back(data_type); } return DataType::ConstPtr(new TupleType(types, true)); } DataType::ConstPtr native_type(native_types.by_class_name(next)); if (native_type) { return native_type; } return DataType::ConstPtr(new CustomType(next)); }