Repository: diesel-rs/diesel
File: diesel/src/pg/connection/raw.rs (Rust)

Code before:
                process_id: unsafe { (*pgnotify).be_pid },
                channel: unsafe { CStr::from_ptr((*pgnotify).relname) }
                    .to_str()
                    .expect("Channel name should be UTF-8")
                    .to_string(),
                payload: unsafe { CStr::from_ptr((*pgnotify).extra) }
                    .to_str()
                    .expect("Could not parse payload to UTF-8")
                    .to_string(),
            });
            unsafe { PQfreemem(pgnotify as *mut std::ffi::c_void) };
            ret
        }
    }
}

// Using the same field names as tokio-postgres
/// See Postgres documentation for SQL Commands NOTIFY and LISTEN
#[derive(Clone, Debug)]
pub struct PGNotification {
    /// process ID of notifying server process
    pub process_id: i32,
    /// Name of the notification channel
    pub channel: String,
    /// optional data that was submitted with the notification, empty string if no data was submitted
    pub payload: String,
}

/// Represents the current in-transaction status of the connection
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub(super) enum PgTransactionStatus {
    /// Currently idle
    Idle,
    /// A command is in progress (sent to the server but not yet completed)
    Active,
    /// Idle, in a valid transaction block
    InTransaction,
    /// Idle, in a failed transaction block
    InError,
    /// Bad connection
    Unknown,
}

impl From<PGTransactionStatusType> for PgTransactionStatus {
    fn from(trans_status_type: PGTransactionStatusType) -> Self {
        match trans_status_type {
            PGTransactionStatusType::PQTRANS_IDLE => PgTransactionStatus::Idle,
            PGTransactionStatusType::PQTRANS_ACTIVE => PgTransactionStatus::Active,
            PGTransactionStatusType::PQTRANS_INTRANS => PgTransactionStatus::InTransaction,
            PGTransactionStatusType::PQTRANS_INERROR => PgTransactionStatus::InError,
            PGTransactionStatusType::PQTRANS_UNKNOWN => PgTransactionStatus::Unknown,

Review comment (suggestion):
If it's optional I would rather prefer to use a `Option<String>` here.

Code after:
            ));
        }

        let pgnotify = unsafe { PQnotifies(conn.as_ptr()) };
        if pgnotify.is_null() {
            Ok(None)
        } else {
            // we use a drop guard here to
            // make sure that we always free
            // the provided pointer, even if we
            // somehow return an error below
            struct Guard<'a> {
                value: &'a mut pgNotify,
            }

            impl Drop for Guard<'_> {
                fn drop(&mut self) {
                    unsafe {
                        // SAFETY: We know that this value is not null here
                        PQfreemem(self.value as *mut pgNotify as *mut std::ffi::c_void)
                    };
                }
            }

            let pgnotify = unsafe {
                // SAFETY: We checked for null values above
                Guard {
                    value: &mut *pgnotify,
                }
            };
            if pgnotify.value.relname.is_null() {
                return Err(Error::DeserializationError(
                    "Received an unexpected null value for `relname` from the notification".into(),
                ));
            }
            if pgnotify.value.extra.is_null() {
                return Err(Error::DeserializationError(
                    "Received an unexpected null value for `extra` from the notification".into(),
                ));
            }

            let channel = unsafe {
                // SAFETY: We checked for null values above
                CStr::from_ptr(pgnotify.value.relname)
            }
            .to_str()
            .map_err(|e| Error::DeserializationError(e.into()))?
            .to_string();
            let payload = unsafe {
                // SAFETY: We checked for null values above
                CStr::from_ptr(pgnotify.value.extra)