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