cslice/
lib.rs

1//! A library of _C-slices_: slices with a stable ABI for interfacing with C.
2//!
3//! This library provides two types, `CSlice` and `CMutSlice`, for communicating
4//! with C about Rust slices or foreign slice-like data structures. Both types
5//! have a stable ABI consisting of exactly two pointer-sized words:
6//!
7//! ```c
8//! struct {
9//!     void *base;
10//!     size_t len;
11//! }
12//! ```
13//!
14//! C-slices and Rust slices are interchangeable, with conversion methods in both
15//! directions.
16//!
17//! This makes it possible to construct slices from foreign code, as well as to
18//! communicate Rust slices to foreign code conveniently.
19
20#![no_std]
21
22use core::{ptr, slice};
23use core::marker::PhantomData;
24use core::ops::{Index, IndexMut};
25
26/// An immutable slice, equivalent to `&'a T`.
27///
28/// A `CSlice` can be constructed from a corresponding Rust slice via the `AsCSlice` trait.
29///
30/// A Rust slice can be constructed from a corresponding `CSlice` via `as_ref`.
31#[repr(C)]
32#[derive(Clone, Copy)]
33pub struct CSlice<'a, T> {
34    base: *const T,
35    len: usize,
36    marker: PhantomData<&'a ()>
37}
38
39impl<'a, T> CSlice<'a, T> {
40    /// Create a `CSlice` from raw data.
41    ///
42    /// # Safety
43    ///
44    /// The region of memory from `base` (inclusive) to `base + len * sizeof<T>`
45    /// (exclusive) must be valid for the duration of lifetime `'a`.
46    pub unsafe fn new(base: *const T, len: usize) -> Self {
47        assert!(base != ptr::null());
48        CSlice {
49            base: base,
50            len: len,
51            marker: PhantomData
52        }
53    }
54
55    /// Produces a raw pointer to the slice's buffer.
56    pub fn as_ptr(&self) -> *const T {
57        self.base
58    }
59
60    /// Returns the number of elements in the slice.
61    pub fn len(&self) -> usize {
62        self.len
63    }
64}
65
66impl<'a, T> AsRef<[T]> for CSlice<'a, T> {
67    fn as_ref(&self) -> &[T] {
68        unsafe {
69            slice::from_raw_parts(self.base, self.len)
70        }
71    }
72}
73
74/// A mutable slice, equivalent to `&'a mut T`.
75///
76/// A `CMutSlice` can be constructed from a corresponding Rust slice via the `AsCMutSlice` trait.
77///
78/// A Rust slice can be constructed from a corresponding `CMutSlice` via `as_mut`.
79#[repr(C)]
80#[derive(Clone, Copy)]
81pub struct CMutSlice<'a, T> {
82    base: *mut T,
83    len: usize,
84    marker: PhantomData<&'a ()>
85}
86
87impl<'a, T> CMutSlice<'a, T> {
88    /// Create a `CSlice` from raw data.
89    ///
90    /// # Safety
91    ///
92    /// The region of memory from `base` (inclusive) to `base + len * sizeof<T>`
93    /// (exclusive) must be valid for the duration of lifetime `'a`.
94    pub unsafe fn new(base: *mut T, len: usize) -> Self {
95        assert!(base != ptr::null_mut());
96        CMutSlice {
97            base: base,
98            len: len,
99            marker: PhantomData
100        }
101    }
102
103    /// Produces a raw pointer to the slice's buffer.
104    pub fn as_ptr(&self) -> *const T {
105        self.base
106    }
107
108    /// Produces a raw pointer to the slice's buffer.
109    pub fn as_mut_ptr(&mut self) -> *mut T {
110        self.base
111    }
112
113    /// A cheap conversion to a Rust slice. This is slightly more general than `as_ref`.
114    pub fn as_slice(&self) -> &'a [T] {
115        unsafe {
116            slice::from_raw_parts(self.base, self.len)
117        }
118    }
119
120    /// A cheap conversion to a mutable Rust slice. This is slightly more general than `as_mut`.
121    pub fn as_mut_slice(&mut self) -> &'a mut [T] {
122        unsafe {
123            slice::from_raw_parts_mut(self.base, self.len)
124        }
125    }
126
127    /// Returns the number of elements in the slice.
128    pub fn len(&self) -> usize {
129        self.len
130    }
131}
132
133impl<'a, T> AsRef<[T]> for CMutSlice<'a, T> {
134    fn as_ref(&self) -> &[T] {
135        unsafe {
136            slice::from_raw_parts(self.base, self.len)
137        }
138    }
139}
140
141impl<'a, T> AsMut<[T]> for CMutSlice<'a, T> {
142    fn as_mut(&mut self) -> &mut [T] {
143        unsafe {
144            slice::from_raw_parts_mut(self.base, self.len)
145        }
146    }
147}
148
149unsafe impl<'a, T: Sync> Sync for CSlice<'a, T> { }
150
151unsafe impl<'a, T: Sync> Send for CSlice<'a, T> { }
152
153unsafe impl<'a, T: Sync> Sync for CMutSlice<'a, T> { }
154
155unsafe impl<'a, T: Send> Send for CMutSlice<'a, T> { }
156
157impl<'a, T> Index<usize> for CSlice<'a, T> {
158    type Output = T;
159
160    fn index(&self, i: usize) -> &T {
161        self.as_ref().index(i)
162    }
163}
164
165impl<'a, T> Index<usize> for CMutSlice<'a, T> {
166    type Output = T;
167
168    fn index(&self, i: usize) -> &T {
169        self.as_ref().index(i)
170    }
171}
172
173impl<'a, T> IndexMut<usize> for CMutSlice<'a, T> {
174    fn index_mut(&mut self, i: usize) -> &mut T {
175        self.as_mut().index_mut(i)
176    }
177}
178
179/// A cheap conversion to a `CSlice`.
180pub trait AsCSlice<'a, T> {
181    /// Performs the conversion.
182    fn as_c_slice(&'a self) -> CSlice<'a, T>;
183}
184
185/// A cheap conversion to a `CMutSlice`.
186pub trait AsCMutSlice<'a, T> {
187    /// Performs the conversion.
188    fn as_c_mut_slice(&'a mut self) -> CMutSlice<'a, T>;
189}
190
191impl<'a> AsCSlice<'a, u8> for str {
192    fn as_c_slice(&'a self) -> CSlice<'a, u8> {
193        CSlice {
194            base: self.as_ptr(),
195            len: self.len(),
196            marker: PhantomData
197        }
198    }
199}
200
201impl<'a, T> AsCSlice<'a, T> for [T] {
202    fn as_c_slice(&'a self) -> CSlice<'a, T> {
203        CSlice {
204            base: self.as_ptr(),
205            len: self.len(),
206            marker: PhantomData
207        }
208    }
209}
210
211impl<'a, T> AsCMutSlice<'a, T> for [T] {
212    fn as_c_mut_slice(&'a mut self) -> CMutSlice<'a, T> {
213        CMutSlice {
214            base: self.as_mut_ptr(),
215            len: self.len(),
216            marker: PhantomData
217        }
218    }
219}