Skip to main content

libhaystack/c_api/
str.rs

1// Copyright (C) 2020 - 2022, J2 Innovations
2
3//!
4//! C API for working with the [Str](crate::val::Str) type.
5//!
6
7use super::err::{new_error, update_last_error};
8use std::ffi::CString;
9use std::os::raw::c_char;
10
11use crate::haystack::val::Value;
12
13/// Get number of character, without trailing zero, of a [Str](crate::val::Str) [Value](crate::val::Value)
14/// # Arguments
15/// val A [Str](crate::val::Str) [Value](crate::val::Value) to get the len from
16/// # Returns
17/// - the size of the string
18/// - -1 (usize::MAX) if there was an error getting the string length, in which case use [last_error_message](super::err::last_error_message)
19/// # Example
20/// ```rust
21/// # use crate::libhaystack::val::Value;
22/// # use crate::libhaystack::c_api::value::*;
23/// # use crate::libhaystack::c_api::str::*;
24/// # unsafe {
25/// let str = std::ffi::CString::new("foo bar").unwrap();
26/// let val = haystack_value_make_str(str.as_ptr());
27/// # let val = Box::<Value>::leak(val.unwrap());
28/// assert!(haystack_value_is_str(val));
29/// assert_eq!(haystack_value_get_str_len(val), 7);
30/// # }
31/// ```
32/// # Safety
33/// Panics on invalid input data
34#[unsafe(no_mangle)]
35pub unsafe extern "C" fn haystack_value_get_str_len(val: *const Value) -> usize {
36    match unsafe { val.as_ref() } {
37        Some(value) => match value {
38            Value::Str(str) => return str.value.len(),
39            _ => new_error("Not a Str Value"),
40        },
41        None => new_error("Invalid Value reference"),
42    };
43    usize::MAX
44}
45
46/// Get the character of a [Str](crate::val::Str) [Value](crate::val::Value)
47/// # Arguments
48/// val A [Str](crate::val::Str) [Value](crate::val::Value) to get the C string from.
49/// # Returns
50/// The C string or `null` if there was an error, in which case the [last_error_message](super::err::last_error_message)
51/// can be called to get the error message.
52/// # Example
53/// ```rust
54/// # use crate::libhaystack::val::Value;
55/// # use crate::libhaystack::c_api::value::*;
56/// # use crate::libhaystack::c_api::str::*;
57/// # unsafe {
58/// let str = std::ffi::CString::new("foo bar").unwrap();
59/// let val = haystack_value_make_str(str.as_ptr());
60/// # let val = Box::<Value>::leak(val.unwrap());
61/// assert!(haystack_value_is_str(val));
62/// let res = haystack_value_get_str_value(val) as *mut i8;
63/// assert_eq!(std::ffi::CString::from_raw(res), str);
64/// # }
65/// ```
66/// # Safety
67/// Panics on invalid input data
68#[unsafe(no_mangle)]
69pub unsafe extern "C" fn haystack_value_get_str_value(val: *const Value) -> *const c_char {
70    match unsafe { val.as_ref() } {
71        Some(value) => match value {
72            Value::Str(str) => match CString::new(str.value.as_bytes()) {
73                Ok(str) => return str.into_raw(),
74                Err(err) => update_last_error(err),
75            },
76            _ => new_error("Not a Str Value"),
77        },
78        None => new_error("Invalid Value reference"),
79    };
80    std::ptr::null()
81}
82
83/// Destructs and free a C Strings allocated by haystack functions
84/// # Arguments
85/// val C String pointer.
86/// # Safety
87/// Panics on invalid input data
88#[unsafe(no_mangle)]
89pub unsafe extern "C" fn haystack_string_destroy(val: *mut c_char) {
90    // Here the ownership of the pointer is taken by CString
91    // which gets destructed at end of scope, so it will free the memory from the pointer also.
92    let _ = unsafe { CString::from_raw(val) };
93}