This is an automated email from the ASF dual-hosted git repository.

astitcher pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-proton.git

commit 2f6350993289699b86f31316b344eb84959fd736
Author: Andrew Stitcher <astitc...@apache.org>
AuthorDate: Tue Aug 13 14:05:03 2024 -0400

    PROTON-2873: Add new C APIs for different disposition types
    
    Change the disposition representation to be a union and add APIs to
    access the various disposition types and their properties.
---
 c/include/proton/disposition.h | 192 +++++++++++++++++++++++++++++++++++++++++
 c/src/core/engine-internal.h   |  18 ++--
 c/src/core/engine.c            | 106 +++++++++++++++++++++++
 python/cproton.h               |  49 +++++++----
 python/cproton.py              |  19 +++-
 5 files changed, 359 insertions(+), 25 deletions(-)

diff --git a/c/include/proton/disposition.h b/c/include/proton/disposition.h
index e80bf8ffd..d809b2100 100644
--- a/c/include/proton/disposition.h
+++ b/c/include/proton/disposition.h
@@ -227,6 +227,198 @@ PN_EXTERN void 
pn_disposition_set_undeliverable(pn_disposition_t *disposition, b
  */
 PN_EXTERN pn_data_t *pn_disposition_annotations(pn_disposition_t *disposition);
 
+/**
+ * A received delivery disposition
+ *
+ * This represents the non terminal delivery received state.
+ */
+typedef struct pn_received_disposition_t pn_received_disposition_t;
+
+/**
+ * A rejected delivery disposition
+ *
+ * This represents the terminal delivery rejected state.
+ */
+typedef struct pn_rejected_disposition_t pn_rejected_disposition_t;
+
+/**
+ * A modified delivery disposition
+ *
+ * This represents the terminal delivery modified state.
+ */
+typedef struct pn_modified_disposition_t pn_modified_disposition_t;
+
+/**
+ * A custom delivery disposition
+ *
+ * This can be used to represent a disposition that is not one of the 
predefined
+ * AMQP delivery dispositions.
+ */
+typedef struct pn_custom_disposition_t pn_custom_disposition_t;
+
+/**
+ * Convert a delivery disposition to a custom disposition
+ *
+ * @param[in] disposition delivery disposition object
+ * @return a pointer to the equivalent custom disposition type
+ */
+PN_EXTERN pn_custom_disposition_t *pn_custom_disposition(pn_disposition_t 
*disposition);
+
+/**
+ * Convert a delivery disposition to a received disposition
+ *
+ * @param[in] disposition delivery disposition object
+ * @return a pointer to the received disposition or NULL
+ * if the disposition is not that type
+ */
+PN_EXTERN pn_received_disposition_t *pn_received_disposition(pn_disposition_t 
*disposition);
+
+/**
+ * Convert a delivery disposition to a rejected disposition
+ *
+ * @param[in] disposition delivery disposition object
+ * @return a pointer to the rejected disposition or NULL
+ * if the disposition is not that type
+ */
+PN_EXTERN pn_rejected_disposition_t *pn_rejected_disposition(pn_disposition_t 
*disposition);
+
+/**
+ * Convert a delivery disposition to a modified disposition
+ *
+ * @param[in] disposition delivery disposition object
+ * @return a pointer to the modified disposition or NULL
+ * if the disposition is not that type
+ */
+PN_EXTERN pn_modified_disposition_t *pn_modified_disposition(pn_disposition_t 
*disposition);
+
+/**
+ * Access the disposition as a raw pn_data_t.
+ *
+ * Dispositions are an extension point in the AMQP protocol. The
+ * disposition interface provides setters/getters for those
+ * dispositions that are predefined by the specification, however
+ * access to the raw disposition data is provided so that other
+ * dispositions can be used.
+ *
+ * The ::pn_data_t pointer returned by this operation is valid until
+ * the parent delivery is settled.
+ *
+ * @param[in] disposition a custom disposition object
+ * @return a pointer to the raw disposition data
+ */
+PN_EXTERN pn_data_t *pn_custom_disposition_data(pn_custom_disposition_t 
*disposition);
+
+/**
+ * Get the type of a custom disposition.
+ *
+ * @param[in] disposition a custom disposition object
+ * @return the type of the disposition
+ */
+PN_EXTERN uint64_t pn_custom_disposition_get_type(pn_custom_disposition_t 
*disposition);
+
+/**
+ * Set the type of a custom disposition.
+ *
+ * @param[in] disposition a custom disposition object
+ * @param[in] type the type of the disposition
+ */
+PN_EXTERN void pn_custom_disposition_set_type(pn_custom_disposition_t 
*disposition, uint64_t type);
+
+/**
+ * Access the condition object associated with a rejected disposition.
+ *
+ * The ::pn_condition_t object retrieved by this operation may be
+ * modified prior to updating a delivery. When a delivery is updated,
+ * the condition described by the disposition is reported to the peer.
+ *
+ * The pointer returned by this operation is valid until the parent
+ * delivery is settled.
+ *
+ * @param[in] disposition a disposition object
+ * @return a pointer to the disposition condition
+ */
+PN_EXTERN pn_condition_t 
*pn_rejected_disposition_condition(pn_rejected_disposition_t *disposition);
+
+/**
+ * Get the section number associated with a received disposition.
+ *
+ * @param[in] disposition a disposition object
+ * @return a section number
+ */
+PN_EXTERN uint32_t 
pn_received_disposition_get_section_number(pn_received_disposition_t 
*disposition);
+
+/**
+ * Set the section number associated with a received disposition.
+ *
+ * @param[in] disposition a disposition object
+ * @param[in] section_number a section number
+ */
+PN_EXTERN void 
pn_received_disposition_set_section_number(pn_received_disposition_t 
*disposition, uint32_t section_number);
+
+/**
+ * Get the section offset associated with a received disposition.
+ *
+ * @param[in] disposition a disposition object
+ * @return a section offset
+ */
+PN_EXTERN uint64_t 
pn_received_disposition_get_section_offset(pn_received_disposition_t 
*disposition);
+
+/**
+ * Set the section offset associated with a received disposition.
+ *
+ * @param[in] disposition a disposition object
+ * @param[in] section_offset a section offset
+ */
+PN_EXTERN void 
pn_received_disposition_set_section_offset(pn_received_disposition_t 
*disposition, uint64_t section_offset);
+
+/**
+ * Check if a modified disposition has the failed flag set.
+ *
+ * @param[in] disposition a disposition object
+ * @return true if the disposition has the failed flag set, false otherwise
+ */
+PN_EXTERN bool pn_modified_disposition_is_failed(pn_modified_disposition_t 
*disposition);
+
+/**
+ * Set the failed flag on a modified disposition.
+ *
+ * @param[in] disposition a disposition object
+ * @param[in] failed the value of the failed flag
+ */
+PN_EXTERN void pn_modified_disposition_set_failed(pn_modified_disposition_t 
*disposition, bool failed);
+
+/**
+ * Check if a modified disposition has the undeliverable flag set.
+ *
+ * @param[in] disposition a disposition object
+ * @return true if the disposition has the undeliverable flag set, false 
otherwise
+ */
+PN_EXTERN bool 
pn_modified_disposition_is_undeliverable(pn_modified_disposition_t 
*disposition);
+
+/**
+ * Set the undeliverable flag on a modified disposition.
+ *
+ * @param[in] disposition a disposition object
+ * @param[in] undeliverable the value of the undeliverable flag
+ */
+PN_EXTERN void 
pn_modified_disposition_set_undeliverable(pn_modified_disposition_t 
*disposition, bool undeliverable);
+
+/**
+ * Access the annotations associated with a modified disposition.
+ *
+ * The ::pn_data_t object retrieved by this operation may be modified
+ * prior to updating a delivery. When a delivery is updated, the
+ * annotations described by the ::pn_data_t are reported to the peer.
+ * The ::pn_data_t must be empty or contain a symbol keyed map.
+ *
+ * The pointer returned by this operation is valid until the parent
+ * delivery is settled.
+ *
+ * @param[in] disposition a disposition object
+ * @return the annotations associated with the disposition
+ */
+PN_EXTERN pn_data_t 
*pn_modified_disposition_annotations(pn_modified_disposition_t *disposition);
+
 /**
  * @}
  */
diff --git a/c/src/core/engine-internal.h b/c/src/core/engine-internal.h
index e0e588b58..da563813a 100644
--- a/c/src/core/engine-internal.h
+++ b/c/src/core/engine-internal.h
@@ -343,27 +343,27 @@ typedef enum pn_disposition_type_t {
   PN_DISP_MODIFIED = PN_MODIFIED,
 } pn_disposition_type_t;
 
-typedef struct pn_received_disposition_t {
+struct pn_received_disposition_t {
   uint64_t section_offset;
   uint32_t section_number;
-} pn_received_disposition_t;
+};
 
-typedef struct pn_rejected_disposition_t {
+struct pn_rejected_disposition_t {
   pn_condition_t condition;
-} pn_rejected_disposition_t;
+};
 
-typedef struct pn_modified_disposition_t {
+struct pn_modified_disposition_t {
   pn_data_t *annotations;
   pn_bytes_t annotations_raw;
   bool failed;
   bool undeliverable;
-} pn_modified_disposition_t;
+};
 
-typedef struct pn_custom_disposition_t {
+struct pn_custom_disposition_t {
   pn_data_t *data;
-  uint64_t   type;
   pn_bytes_t data_raw;
-} pn_custom_disposition_t;
+  uint64_t   type;
+};
 
 struct pn_disposition_t {
   union {
diff --git a/c/src/core/engine.c b/c/src/core/engine.c
index ad9e77fd5..7ccb308b9 100644
--- a/c/src/core/engine.c
+++ b/c/src/core/engine.c
@@ -1978,6 +1978,112 @@ pn_condition_t 
*pn_disposition_condition(pn_disposition_t *disposition)
   return &disposition->u.s_rejected.condition;
 }
 
+pn_custom_disposition_t *pn_custom_disposition(pn_disposition_t *disposition)
+{
+  pni_disposition_to_raw(disposition);
+  return &disposition->u.s_custom;
+}
+
+pn_received_disposition_t *pn_received_disposition(pn_disposition_t 
*disposition)
+{
+  if (disposition->type==PN_DISP_EMPTY) disposition->type = PN_DISP_RECEIVED;
+  else if (disposition->type!=PN_DISP_RECEIVED) return NULL;
+  return &disposition->u.s_received;
+}
+
+pn_rejected_disposition_t *pn_rejected_disposition(pn_disposition_t 
*disposition)
+{
+  if (disposition->type==PN_DISP_EMPTY) disposition->type = PN_DISP_REJECTED;
+  else if (disposition->type!=PN_DISP_REJECTED) return NULL;
+  return &disposition->u.s_rejected;
+}
+
+pn_modified_disposition_t *pn_modified_disposition(pn_disposition_t 
*disposition)
+{
+  if (disposition->type==PN_DISP_EMPTY) disposition->type = PN_DISP_MODIFIED;
+  else if (disposition->type!=PN_DISP_MODIFIED) return NULL;
+  return &disposition->u.s_modified;
+}
+
+pn_data_t *pn_custom_disposition_data(pn_custom_disposition_t *disposition)
+{
+  assert(disposition);
+  pni_switch_to_data(&disposition->data_raw, &disposition->data);
+  return disposition->data;
+}
+
+uint64_t pn_custom_disposition_get_type(pn_custom_disposition_t *disposition)
+{
+  assert(disposition);
+  return disposition->type;
+}
+
+void pn_custom_disposition_set_type(pn_custom_disposition_t *disposition, 
uint64_t type)
+{
+  assert(disposition);
+  disposition->type = type;
+}
+
+pn_condition_t *pn_rejected_disposition_condition(pn_rejected_disposition_t 
*disposition)
+{
+  assert(disposition);
+  return &disposition->condition;
+}
+
+uint32_t pn_received_disposition_get_section_number(pn_received_disposition_t 
*disposition)
+{
+  assert(disposition);
+  return disposition->section_number;
+}
+
+void pn_received_disposition_set_section_number(pn_received_disposition_t 
*disposition, uint32_t section_number)
+{
+  assert(disposition);
+  disposition->section_number = section_number;
+}
+
+uint64_t pn_received_disposition_get_section_offset(pn_received_disposition_t 
*disposition)
+{
+  assert(disposition);
+  return disposition->section_offset;
+}
+
+void pn_received_disposition_set_section_offset(pn_received_disposition_t 
*disposition, uint64_t section_offset)
+{
+  assert(disposition);
+  disposition->section_offset = section_offset;
+}
+
+bool pn_modified_disposition_is_failed(pn_modified_disposition_t *disposition) 
{
+  assert(disposition);
+  return disposition->failed;
+}
+
+void pn_modified_disposition_set_failed(pn_modified_disposition_t 
*disposition, bool failed)
+{
+  assert(disposition);
+  disposition->failed = failed;
+}
+
+bool pn_modified_disposition_is_undeliverable(pn_modified_disposition_t 
*disposition)
+{
+  assert(disposition);
+  return disposition->undeliverable;
+}
+
+void pn_modified_disposition_set_undeliverable(pn_modified_disposition_t 
*disposition, bool undeliverable)
+{
+  assert(disposition);
+  disposition->undeliverable = undeliverable;
+}
+
+pn_data_t *pn_modified_disposition_annotations(pn_modified_disposition_t 
*disposition)
+{
+  assert(disposition);
+  pni_switch_to_data(&disposition->annotations_raw, &disposition->annotations);
+  return disposition->annotations;
+}
+
 pn_delivery_tag_t pn_delivery_tag(pn_delivery_t *delivery)
 {
   if (delivery) {
diff --git a/python/cproton.h b/python/cproton.h
index 29dc30ba4..f98915693 100644
--- a/python/cproton.h
+++ b/python/cproton.h
@@ -29,7 +29,7 @@ typedef struct pn_collector_t pn_collector_t;
 typedef struct pn_condition_t pn_condition_t;
 typedef struct pn_connection_t pn_connection_t;
 typedef struct pn_data_t pn_data_t;
-typedef struct 
+typedef struct
 {
   char bytes[16];
 } pn_decimal128_t;
@@ -38,13 +38,13 @@ typedef uint64_t pn_decimal64_t;
 typedef struct pn_delivery_t pn_delivery_t;
 typedef pn_bytes_t pn_delivery_tag_t;
 typedef struct pn_disposition_t pn_disposition_t;
-typedef enum 
+typedef enum
 {
   PN_DIST_MODE_UNSPECIFIED = 0,
   PN_DIST_MODE_COPY = 1,
   PN_DIST_MODE_MOVE = 2
 } pn_distribution_mode_t;
-typedef enum 
+typedef enum
 {
   PN_NONDURABLE = 0,
   PN_CONFIGURATION = 1,
@@ -52,7 +52,7 @@ typedef enum
 } pn_durability_t;
 typedef struct pn_error_t pn_error_t;
 typedef struct pn_event_t pn_event_t;
-typedef enum 
+typedef enum
 {
   PN_EVENT_NONE = 0,
   PN_REACTOR_INIT,
@@ -114,7 +114,7 @@ typedef enum
   PN_RAW_CONNECTION_WAKE,
   PN_RAW_CONNECTION_DRAIN_BUFFERS
 } pn_event_type_t;
-typedef enum 
+typedef enum
 {
   PN_EXPIRE_WITH_LINK,
   PN_EXPIRE_WITH_SESSION,
@@ -130,7 +130,7 @@ typedef enum
   PN_RCV_SECOND = 1
 } pn_rcv_settle_mode_t;
 typedef struct pn_record_t pn_record_t;
-typedef enum 
+typedef enum
 {
   PN_SASL_NONE = -1,
   PN_SASL_OK = 0,
@@ -143,13 +143,13 @@ typedef struct pn_sasl_t pn_sasl_t;
 typedef uint32_t pn_seconds_t;
 typedef uint32_t pn_sequence_t;
 typedef struct pn_session_t pn_session_t;
-typedef enum 
+typedef enum
 {
   PN_SND_UNSETTLED = 0,
   PN_SND_SETTLED = 1,
   PN_SND_MIXED = 2
 } pn_snd_settle_mode_t;
-typedef enum 
+typedef enum
 {
   PN_SSL_CERT_SUBJECT_COUNTRY_NAME,
   PN_SSL_CERT_SUBJECT_STATE_OR_PROVINCE,
@@ -159,26 +159,26 @@ typedef enum
   PN_SSL_CERT_SUBJECT_COMMON_NAME
 } pn_ssl_cert_subject_subfield;
 typedef struct pn_ssl_domain_t pn_ssl_domain_t;
-typedef enum 
+typedef enum
 {
   PN_SSL_SHA1,
   PN_SSL_SHA256,
   PN_SSL_SHA512,
   PN_SSL_MD5
 } pn_ssl_hash_alg;
-typedef enum 
+typedef enum
 {
   PN_SSL_MODE_CLIENT = 1,
   PN_SSL_MODE_SERVER
 } pn_ssl_mode_t;
-typedef enum 
+typedef enum
 {
   PN_SSL_RESUME_UNKNOWN,
   PN_SSL_RESUME_NEW,
   PN_SSL_RESUME_REUSED
 } pn_ssl_resume_status_t;
 typedef struct pn_ssl_t pn_ssl_t;
-typedef enum 
+typedef enum
 {
   PN_SSL_VERIFY_NULL = 0,
   PN_SSL_VERIFY_PEER,
@@ -187,7 +187,7 @@ typedef enum
 } pn_ssl_verify_mode_t;
 typedef int pn_state_t;
 typedef struct pn_terminus_t pn_terminus_t;
-typedef enum 
+typedef enum
 {
   PN_UNSPECIFIED = 0,
   PN_SOURCE = 1,
@@ -197,7 +197,7 @@ typedef enum
 typedef int64_t pn_timestamp_t;
 typedef int pn_trace_t;
 typedef struct pn_transport_t pn_transport_t;
-typedef enum 
+typedef enum
 {
   PN_NULL = 1,
   PN_BOOL = 2,
@@ -226,7 +226,7 @@ typedef enum
   PN_MAP = 25,
   PN_INVALID = -1
 } pn_type_t;
-typedef struct 
+typedef struct
 {
   char bytes[16];
 } pn_uuid_t;
@@ -406,6 +406,25 @@ void pn_disposition_set_section_offset(pn_disposition_t 
*disposition, uint64_t s
 void pn_disposition_set_undeliverable(pn_disposition_t *disposition, _Bool 
undeliverable);
 uint64_t pn_disposition_type(pn_disposition_t *disposition);
 
+typedef struct pn_received_disposition_t pn_received_disposition_t;
+typedef struct pn_rejected_disposition_t pn_rejected_disposition_t;
+typedef struct pn_modified_disposition_t pn_modified_disposition_t;
+
+pn_received_disposition_t *pn_received_disposition(pn_disposition_t 
*disposition);
+pn_rejected_disposition_t *pn_rejected_disposition(pn_disposition_t 
*disposition);
+pn_modified_disposition_t *pn_modified_disposition(pn_disposition_t 
*disposition);
+
+pn_condition_t *pn_rejected_disposition_condition(pn_rejected_disposition_t 
*disposition);
+uint32_t pn_received_disposition_get_section_number(pn_received_disposition_t 
*disposition);
+void pn_received_disposition_set_section_number(pn_received_disposition_t 
*disposition, uint32_t section_number);
+uint64_t pn_received_disposition_get_section_offset(pn_received_disposition_t 
*disposition);
+void pn_received_disposition_set_section_offset(pn_received_disposition_t 
*disposition, uint64_t section_offset);
+_Bool pn_modified_disposition_is_failed(pn_modified_disposition_t 
*disposition);
+void pn_modified_disposition_set_failed(pn_modified_disposition_t 
*disposition, _Bool failed);
+_Bool pn_modified_disposition_is_undeliverable(pn_modified_disposition_t 
*disposition);
+void pn_modified_disposition_set_undeliverable(pn_modified_disposition_t 
*disposition, _Bool undeliverable);
+pn_data_t *pn_modified_disposition_annotations(pn_modified_disposition_t 
*disposition);
+
 int pn_error_code(pn_error_t *error);
 const char *pn_error_text(pn_error_t *error);
 
diff --git a/python/cproton.py b/python/cproton.py
index 6be8711d8..1dea17ac1 100644
--- a/python/cproton.py
+++ b/python/cproton.py
@@ -158,7 +158,24 @@ from cproton_ffi.lib import (PN_ACCEPTED, PN_ARRAY, 
PN_BINARY, PN_BOOL, PN_BYTE,
                              pn_transport_require_encryption, 
pn_transport_set_channel_max,
                              pn_transport_set_idle_timeout, 
pn_transport_set_max_frame,
                              pn_transport_set_server, pn_transport_tick, 
pn_transport_trace,
-                             pn_transport_unbind)
+                             pn_transport_unbind,
+                             pn_custom_disposition,
+                             pn_custom_disposition_get_type,
+                             pn_custom_disposition_set_type,
+                             pn_custom_disposition_data,
+                             pn_rejected_disposition,
+                             pn_rejected_disposition_condition,
+                             pn_received_disposition,
+                             pn_received_disposition_get_section_number,
+                             pn_received_disposition_set_section_number,
+                             pn_received_disposition_get_section_offset,
+                             pn_received_disposition_set_section_offset,
+                             pn_modified_disposition,
+                             pn_modified_disposition_is_failed,
+                             pn_modified_disposition_set_failed,
+                             pn_modified_disposition_is_undeliverable,
+                             pn_modified_disposition_set_undeliverable,
+                             pn_modified_disposition_annotations)
 
 
 def isnull(obj):


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@qpid.apache.org
For additional commands, e-mail: commits-h...@qpid.apache.org

Reply via email to