1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4 
5 use libc::size_t;
6 use std::boxed::Box;
7 use std::convert::TryInto;
8 use std::error::Error;
9 use std::ffi::CStr;
10 use std::{slice, str};
11 
12 use nserror::{nsresult, NS_ERROR_INVALID_ARG, NS_OK};
13 
14 use rsdparsa::attribute_type::SdpAttributeSsrc;
15 
16 #[repr(C)]
17 #[derive(Clone, Copy)]
18 pub struct StringView {
19     buffer: *const u8,
20     len: size_t,
21 }
22 
23 pub const NULL_STRING: StringView = StringView {
24     buffer: 0 as *const u8,
25     len: 0,
26 };
27 
28 impl<'a> From<&'a str> for StringView {
from(input: &str) -> StringView29     fn from(input: &str) -> StringView {
30         StringView {
31             buffer: input.as_ptr(),
32             len: input.len(),
33         }
34     }
35 }
36 
37 impl TryInto<String> for StringView {
38     type Error = Box<dyn Error>;
try_into(self) -> Result<String, Box<dyn Error>>39     fn try_into(self) -> Result<String, Box<dyn Error>> {
40         // This block must be unsafe as it converts a StringView, most likly provided from the
41         // C++ code, into a rust String and thus needs to operate with raw pointers.
42         let string_slice: &[u8];
43         unsafe {
44             // Add one to the length as the length passed in the StringView is the length of
45             // the string and is missing the null terminator
46             string_slice = slice::from_raw_parts(self.buffer, self.len + 1 as usize);
47         }
48 
49         let c_str = match CStr::from_bytes_with_nul(string_slice) {
50             Ok(string) => string,
51             Err(x) => {
52                 return Err(Box::new(x));
53             }
54         };
55 
56         let str_slice: &str = match str::from_utf8(c_str.to_bytes()) {
57             Ok(string) => string,
58             Err(x) => {
59                 return Err(Box::new(x));
60             }
61         };
62 
63         Ok(str_slice.to_string())
64     }
65 }
66 
67 impl<'a, T: AsRef<str>> From<&'a Option<T>> for StringView {
from(input: &Option<T>) -> StringView68     fn from(input: &Option<T>) -> StringView {
69         match *input {
70             Some(ref x) => StringView {
71                 buffer: x.as_ref().as_ptr(),
72                 len: x.as_ref().len(),
73             },
74             None => NULL_STRING,
75         }
76     }
77 }
78 
79 #[no_mangle]
string_vec_len(vec: *const Vec<String>) -> size_t80 pub unsafe extern "C" fn string_vec_len(vec: *const Vec<String>) -> size_t {
81     (*vec).len() as size_t
82 }
83 
84 #[no_mangle]
string_vec_get_view( vec: *const Vec<String>, index: size_t, ret: *mut StringView, ) -> nsresult85 pub unsafe extern "C" fn string_vec_get_view(
86     vec: *const Vec<String>,
87     index: size_t,
88     ret: *mut StringView,
89 ) -> nsresult {
90     match (*vec).get(index) {
91         Some(ref string) => {
92             *ret = StringView::from(string.as_str());
93             NS_OK
94         }
95         None => NS_ERROR_INVALID_ARG,
96     }
97 }
98 
99 #[no_mangle]
free_boxed_string_vec(ptr: *mut Vec<String>) -> nsresult100 pub unsafe extern "C" fn free_boxed_string_vec(ptr: *mut Vec<String>) -> nsresult {
101     drop(Box::from_raw(ptr));
102     NS_OK
103 }
104 
105 #[no_mangle]
f32_vec_len(vec: *const Vec<f32>) -> size_t106 pub unsafe extern "C" fn f32_vec_len(vec: *const Vec<f32>) -> size_t {
107     (*vec).len()
108 }
109 
110 #[no_mangle]
f32_vec_get( vec: *const Vec<f32>, index: size_t, ret: *mut f32, ) -> nsresult111 pub unsafe extern "C" fn f32_vec_get(
112     vec: *const Vec<f32>,
113     index: size_t,
114     ret: *mut f32,
115 ) -> nsresult {
116     match (*vec).get(index) {
117         Some(val) => {
118             *ret = *val;
119             NS_OK
120         }
121         None => NS_ERROR_INVALID_ARG,
122     }
123 }
124 
125 #[no_mangle]
u32_vec_len(vec: *const Vec<u32>) -> size_t126 pub unsafe extern "C" fn u32_vec_len(vec: *const Vec<u32>) -> size_t {
127     (*vec).len()
128 }
129 
130 #[no_mangle]
u32_vec_get( vec: *const Vec<u32>, index: size_t, ret: *mut u32, ) -> nsresult131 pub unsafe extern "C" fn u32_vec_get(
132     vec: *const Vec<u32>,
133     index: size_t,
134     ret: *mut u32,
135 ) -> nsresult {
136     match (*vec).get(index) {
137         Some(val) => {
138             *ret = *val;
139             NS_OK
140         }
141         None => NS_ERROR_INVALID_ARG,
142     }
143 }
144 
145 #[no_mangle]
u16_vec_len(vec: *const Vec<u16>) -> size_t146 pub unsafe extern "C" fn u16_vec_len(vec: *const Vec<u16>) -> size_t {
147     (*vec).len()
148 }
149 
150 #[no_mangle]
u16_vec_get( vec: *const Vec<u16>, index: size_t, ret: *mut u16, ) -> nsresult151 pub unsafe extern "C" fn u16_vec_get(
152     vec: *const Vec<u16>,
153     index: size_t,
154     ret: *mut u16,
155 ) -> nsresult {
156     match (*vec).get(index) {
157         Some(val) => {
158             *ret = *val;
159             NS_OK
160         }
161         None => NS_ERROR_INVALID_ARG,
162     }
163 }
164 
165 #[no_mangle]
u8_vec_len(vec: *const Vec<u8>) -> size_t166 pub unsafe extern "C" fn u8_vec_len(vec: *const Vec<u8>) -> size_t {
167     (*vec).len()
168 }
169 
170 #[no_mangle]
u8_vec_get(vec: *const Vec<u8>, index: size_t, ret: *mut u8) -> nsresult171 pub unsafe extern "C" fn u8_vec_get(vec: *const Vec<u8>, index: size_t, ret: *mut u8) -> nsresult {
172     match (*vec).get(index) {
173         Some(val) => {
174             *ret = *val;
175             NS_OK
176         }
177         None => NS_ERROR_INVALID_ARG,
178     }
179 }
180 
181 #[no_mangle]
ssrc_vec_len(vec: *const Vec<SdpAttributeSsrc>) -> size_t182 pub unsafe extern "C" fn ssrc_vec_len(vec: *const Vec<SdpAttributeSsrc>) -> size_t {
183     (*vec).len()
184 }
185 
186 #[no_mangle]
ssrc_vec_get_id( vec: *const Vec<SdpAttributeSsrc>, index: size_t, ret: *mut u32, ) -> nsresult187 pub unsafe extern "C" fn ssrc_vec_get_id(
188     vec: *const Vec<SdpAttributeSsrc>,
189     index: size_t,
190     ret: *mut u32,
191 ) -> nsresult {
192     match (*vec).get(index) {
193         Some(val) => {
194             *ret = val.id;
195             NS_OK
196         }
197         None => NS_ERROR_INVALID_ARG,
198     }
199 }
200