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