rice_ctypes/
lib.rs

1// Copyright (C) 2025 Matthew Waters <matthew@centricular.com>
2//
3// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. This file may not be copied, modified, or distributed
7// except according to those terms.
8
9#![deny(missing_debug_implementations)]
10#![deny(missing_docs)]
11#![allow(clippy::missing_safety_doc)]
12
13//! # rice-ctypes
14//!
15//! Helper crate for providing C types for the rice API.
16
17use core::ffi::CStr;
18use core::ffi::{c_char, c_int};
19use core::net::SocketAddr;
20use core::str::FromStr;
21
22/// Errors when processing an operation.
23#[repr(i32)]
24#[derive(Debug, PartialEq, Eq, Copy, Clone)]
25pub enum RiceError {
26    /// Not an error. The operation was completed successfully.
27    Success = 0,
28    /// The operation failed for an unspecified reason.
29    Failed = -1,
30    /// A required resource was not found.
31    ResourceNotFound = -2,
32    /// The operation is already in progress.
33    AlreadyInProgress = -3,
34}
35
36/// A socket address.
37#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
38pub struct RiceAddress(SocketAddr);
39
40impl RiceAddress {
41    /// Create a new `RiceAddress`.
42    pub fn new(addr: SocketAddr) -> Self {
43        Self(addr)
44    }
45
46    /// Convert this `RiceAddress` into it's C API equivalent.
47    ///
48    /// The returned value should be converted back into the Rust equivalent using
49    /// `RiceAddress::into_rust_full()` in order to free the resource.
50    pub fn into_c_full(self) -> *const RiceAddress {
51        const_override(Box::into_raw(Box::new(self)))
52    }
53
54    /// Consume a C representation of a `RiceAddress` into the Rust equivalent.
55    pub unsafe fn into_rice_full(value: *const RiceAddress) -> Box<Self> {
56        unsafe { Box::from_raw(mut_override(value)) }
57    }
58
59    /// Copy a C representation of a `RiceAddress` into the Rust equivalent.
60    pub unsafe fn into_rice_none(value: *const RiceAddress) -> Self {
61        unsafe {
62            let boxed = Box::from_raw(mut_override(value));
63            let ret = *boxed;
64            core::mem::forget(boxed);
65            ret
66        }
67    }
68
69    /// The inner representation of the [`RiceAddress`].
70    pub fn inner(self) -> SocketAddr {
71        self.0
72    }
73}
74
75impl core::ops::Deref for RiceAddress {
76    type Target = SocketAddr;
77    fn deref(&self) -> &Self::Target {
78        &self.0
79    }
80}
81
82/// Create a `RiceAddress` from a string representation of the socket address.
83pub unsafe fn rice_address_new_from_string(string: *const c_char) -> *mut RiceAddress {
84    unsafe {
85        let Ok(string) = CStr::from_ptr(string).to_str() else {
86            return core::ptr::null_mut();
87        };
88        let Ok(saddr) = SocketAddr::from_str(string) else {
89            return core::ptr::null_mut();
90        };
91
92        mut_override(RiceAddress::into_c_full(RiceAddress::new(saddr)))
93    }
94}
95
96/// Compare whether two `RiceAddress`es are equal.
97pub unsafe fn rice_address_cmp(addr: *const RiceAddress, other: *const RiceAddress) -> c_int {
98    unsafe {
99        match (addr.is_null(), other.is_null()) {
100            (true, true) => 0,
101            (true, false) => -1,
102            (false, true) => 1,
103            (false, false) => {
104                let addr = RiceAddress::into_rice_none(addr);
105                let other = RiceAddress::into_rice_none(other);
106                addr.cmp(&other) as c_int
107            }
108        }
109    }
110}
111
112/// Free a `RiceAddress`.
113pub unsafe fn rice_address_free(addr: *mut RiceAddress) {
114    unsafe {
115        if !addr.is_null() {
116            let _addr = Box::from_raw(addr);
117        }
118    }
119}
120
121/// The transport family
122#[derive(Debug, Clone, Copy, PartialEq, Eq)]
123#[repr(u32)]
124pub enum RiceTransportType {
125    /// The UDP transport
126    Udp,
127    /// The TCP transport
128    Tcp,
129}
130
131fn mut_override<T>(val: *const T) -> *mut T {
132    val as *mut T
133}
134
135fn const_override<T>(val: *mut T) -> *const T {
136    val as *const T
137}