Skip to main content

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