/*! * Create a submessage within a message for a specific tag. * * \param[in,out] message Message * \param[in] tag Tag * \return Submessage */ extern pb_message_t pb_message_create_within(pb_message_t *message, pb_tag_t tag) { assert(message && tag); if (pb_message_valid(message)) { const pb_field_descriptor_t *descriptor = pb_descriptor_field_by_tag(message->descriptor, tag); assert(descriptor && pb_field_descriptor_type(descriptor) == PB_TYPE_MESSAGE && pb_field_descriptor_nested(descriptor)); pb_message_t submessage = { .descriptor = pb_field_descriptor_nested(descriptor), .part = pb_part_create(message, tag) }; return submessage; } return pb_message_create_invalid(); } /*! * Create a submessage within a nested message for a branch of tags. * * \warning All messages on the branch of tags except the leaf may not occur * repeatedly, but must be defined as optional or required. * * \param[in,out] message Message * \param[in] tags[] Tags * \param[in] size Tag count * \return Submessage */ extern pb_message_t pb_message_create_nested( pb_message_t *message, const pb_tag_t tags[], size_t size) { assert(message && tags && size); pb_message_t prev = pb_message_create_invalid(), this = pb_message_copy(message); for (size_t t = 0; t < size && pb_message_valid(&this); ++t) { pb_message_destroy(&prev); #ifndef NDEBUG /* Assert non-repeated non-leaf messages */ const pb_field_descriptor_t *descriptor = pb_descriptor_field_by_tag(this.descriptor, tags[t]); assert(descriptor && ( pb_field_descriptor_type(descriptor) == PB_TYPE_MESSAGE && ( pb_field_descriptor_label(descriptor) != PB_LABEL_REPEATED || t == size - 1))); #endif /* NDEBUG */ /* Swap messages and create a new one within */ prev = this; this = pb_message_create_within(&prev, tags[t]); } pb_message_destroy(&prev); return this; }
} END_TEST /* * Create a part from an invalid message for a specific tag. */ START_TEST(test_create_message_invalid) { pb_message_t message = pb_message_create_invalid(); pb_part_t part = pb_part_create(&message, 1); /* Assert part validity and error */ fail_if(pb_part_valid(&part)); ck_assert_uint_eq(PB_ERROR_INVALID, pb_part_error(&part)); /* Free all allocated memory */ pb_part_destroy(&part); pb_message_destroy(&message); } END_TEST