eccodes/intermediate_bindings/
codes_get.rs

1#![allow(non_camel_case_types)]
2#![allow(clippy::module_name_repetitions)]
3
4use std::ffi::{CStr, CString};
5
6use eccodes_sys::codes_handle;
7use libc::c_void;
8use num_traits::FromPrimitive;
9
10use crate::{
11    errors::{CodesError, CodesInternal},
12    pointer_guard,
13};
14
15use super::NativeKeyType;
16
17pub unsafe fn codes_get_native_type(
18    handle: *const codes_handle,
19    key: &str,
20) -> Result<NativeKeyType, CodesError> {
21    pointer_guard::non_null!(handle);
22
23    let key = CString::new(key).unwrap();
24    let mut key_type: i32 = 0;
25
26    let error_code = eccodes_sys::codes_get_native_type(handle, key.as_ptr(), &mut key_type);
27
28    if error_code != 0 {
29        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
30        return Err(err.into());
31    }
32
33    Ok(FromPrimitive::from_i32(key_type).unwrap())
34}
35
36pub unsafe fn codes_get_size(handle: *const codes_handle, key: &str) -> Result<usize, CodesError> {
37    pointer_guard::non_null!(handle);
38
39    let key = CString::new(key).unwrap();
40    let mut key_size: usize = 0;
41
42    let error_code = eccodes_sys::codes_get_size(handle, key.as_ptr(), &mut key_size);
43
44    if error_code != 0 {
45        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
46        return Err(err.into());
47    }
48
49    Ok(key_size)
50}
51
52pub unsafe fn codes_get_long(handle: *const codes_handle, key: &str) -> Result<i64, CodesError> {
53    pointer_guard::non_null!(handle);
54
55    let key = CString::new(key).unwrap();
56    let mut key_value: i64 = 0;
57
58    let error_code = eccodes_sys::codes_get_long(handle, key.as_ptr(), &mut key_value);
59
60    if error_code != 0 {
61        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
62        return Err(err.into());
63    }
64
65    Ok(key_value)
66}
67
68pub unsafe fn codes_get_double(handle: *const codes_handle, key: &str) -> Result<f64, CodesError> {
69    pointer_guard::non_null!(handle);
70
71    let key = CString::new(key).unwrap();
72    let mut key_value: f64 = 0.0;
73
74    let error_code = eccodes_sys::codes_get_double(handle, key.as_ptr(), &mut key_value);
75
76    if error_code != 0 {
77        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
78        return Err(err.into());
79    }
80
81    Ok(key_value)
82}
83
84pub unsafe fn codes_get_double_array(
85    handle: *const codes_handle,
86    key: &str,
87) -> Result<Vec<f64>, CodesError> {
88    pointer_guard::non_null!(handle);
89
90    let mut key_size = codes_get_size(handle, key)?;
91    let key = CString::new(key).unwrap();
92
93    let mut key_values: Vec<f64> = vec![0.0; key_size];
94
95    let error_code = eccodes_sys::codes_get_double_array(
96        handle,
97        key.as_ptr(),
98        key_values.as_mut_ptr().cast::<f64>(),
99        &mut key_size,
100    );
101
102    if error_code != 0 {
103        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
104        return Err(err.into());
105    }
106
107    Ok(key_values)
108}
109
110pub unsafe fn codes_get_long_array(
111    handle: *const codes_handle,
112    key: &str,
113) -> Result<Vec<i64>, CodesError> {
114    pointer_guard::non_null!(handle);
115
116    let mut key_size = codes_get_size(handle, key)?;
117    let key = CString::new(key).unwrap();
118
119    let mut key_values: Vec<i64> = vec![0; key_size];
120
121    let error_code = eccodes_sys::codes_get_long_array(
122        handle,
123        key.as_ptr(),
124        key_values.as_mut_ptr().cast::<i64>(),
125        &mut key_size,
126    );
127
128    if error_code != 0 {
129        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
130        return Err(err.into());
131    }
132
133    Ok(key_values)
134}
135
136pub unsafe fn codes_get_length(
137    handle: *const codes_handle,
138    key: &str,
139) -> Result<usize, CodesError> {
140    pointer_guard::non_null!(handle);
141
142    let key = CString::new(key).unwrap();
143    let mut key_length: usize = 0;
144
145    let error_code = eccodes_sys::codes_get_length(handle, key.as_ptr(), &mut key_length);
146
147    if error_code != 0 {
148        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
149        return Err(err.into());
150    }
151
152    Ok(key_length)
153}
154
155pub unsafe fn codes_get_string(
156    handle: *const codes_handle,
157    key: &str,
158) -> Result<String, CodesError> {
159    pointer_guard::non_null!(handle);
160
161    let mut key_length = codes_get_length(handle, key)?;
162    let key = CString::new(key).unwrap();
163
164    let mut key_message: Vec<u8> = vec![0; key_length];
165
166    let error_code = eccodes_sys::codes_get_string(
167        handle,
168        key.as_ptr(),
169        key_message.as_mut_ptr().cast::<i8>(),
170        &mut key_length,
171    );
172
173    if error_code != 0 {
174        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
175        return Err(err.into());
176    }
177
178    key_message.truncate(key_length);
179    let key_message_result = CStr::from_bytes_with_nul(key_message.as_ref());
180
181    let key_message_cstr = if let Ok(msg) = key_message_result {
182        msg
183    } else {
184        key_message.push(0);
185        CStr::from_bytes_with_nul(key_message.as_ref())?
186    };
187
188    let key_message_string = key_message_cstr.to_str()?.to_string();
189
190    Ok(key_message_string)
191}
192
193pub unsafe fn codes_get_bytes(
194    handle: *const codes_handle,
195    key: &str,
196) -> Result<Vec<u8>, CodesError> {
197    pointer_guard::non_null!(handle);
198
199    let mut key_size = codes_get_length(handle, key)?;
200    let key = CString::new(key).unwrap();
201
202    let mut buffer: Vec<u8> = vec![0; key_size];
203
204    let error_code = eccodes_sys::codes_get_bytes(
205        handle,
206        key.as_ptr(),
207        buffer.as_mut_ptr().cast::<u8>(),
208        &mut key_size,
209    );
210
211    if error_code != 0 {
212        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
213        return Err(err.into());
214    }
215
216    Ok(buffer)
217}
218
219pub unsafe fn codes_get_message_size(handle: *const codes_handle) -> Result<usize, CodesError> {
220    pointer_guard::non_null!(handle);
221
222    let mut size: usize = 0;
223
224    let error_code = eccodes_sys::codes_get_message_size(handle, &mut size);
225
226    if error_code != 0 {
227        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
228        return Err(err.into());
229    }
230
231    Ok(size)
232}
233
234pub unsafe fn codes_get_message(
235    handle: *const codes_handle,
236) -> Result<(*const c_void, usize), CodesError> {
237    pointer_guard::non_null!(handle);
238
239    let buffer_size = codes_get_message_size(handle)?;
240
241    let buffer: Vec<u8> = vec![0; buffer_size];
242    let mut buffer_ptr = buffer.as_ptr().cast::<libc::c_void>();
243
244    let mut message_size: usize = 0;
245
246    let error_code = eccodes_sys::codes_get_message(handle, &mut buffer_ptr, &mut message_size);
247
248    if error_code != 0 {
249        let err: CodesInternal = FromPrimitive::from_i32(error_code).unwrap();
250        return Err(err.into());
251    }
252
253    assert!(
254        buffer_size == message_size,
255        "Buffer and message sizes ar not equal in codes_get_message! 
256        Please report this panic on Github."
257    );
258
259    Ok((buffer_ptr, message_size))
260}