-
Notifications
You must be signed in to change notification settings - Fork 167
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(rs-port2): build the base of the values
- implement a constructor and `get_value` for - i16, i32, i64 - f32, f64 - String, &str - implement those methods for Value<T>: - `is_null()` - `value_id()` - `value_id_name()`
- Loading branch information
Showing
6 changed files
with
291 additions
and
54 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
use std::marker::PhantomData; | ||
|
||
use crate::{check_null_ptr, impl_value_constructor}; | ||
|
||
use super::{Value, ValueError}; | ||
use anyhow::Result; | ||
use metacall_bindings::value::{ | ||
create::{metacall_value_create_double, metacall_value_create_float}, | ||
metacall_value_to_double, metacall_value_to_float, | ||
}; | ||
impl Value<f32> { | ||
pub fn get_value(&self) -> Result<f32> { | ||
let res = unsafe { metacall_value_to_float(self.ptr).to_owned() }; | ||
|
||
Ok(res) | ||
} | ||
} | ||
|
||
impl_value_constructor!( | ||
value => { | ||
let ptr = unsafe { metacall_value_create_float(value.into()) }; | ||
|
||
check_null_ptr!(ptr, ValueError::NullPointer); | ||
|
||
Ok(Self { | ||
ptr, | ||
_phantom: PhantomData, | ||
}) | ||
}, f32 | ||
); | ||
|
||
impl Value<f64> { | ||
pub fn get_value(&self) -> Result<f64> { | ||
let res = unsafe { metacall_value_to_double(self.ptr).to_owned() }; | ||
|
||
Ok(res) | ||
} | ||
} | ||
|
||
impl_value_constructor!( | ||
value => { | ||
let ptr = unsafe { metacall_value_create_double(value) }; | ||
|
||
check_null_ptr!(ptr, ValueError::NullPointer); | ||
|
||
Ok(Self { | ||
ptr, | ||
_phantom: PhantomData, | ||
}) | ||
}, f64 | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
use std::marker::PhantomData; | ||
|
||
use anyhow::Result; | ||
use metacall_bindings::value::{ | ||
create::{metacall_value_create_int, metacall_value_create_long}, | ||
metacall_value_to_int, metacall_value_to_long, | ||
}; | ||
|
||
use crate::{check_null_ptr, impl_value_constructor}; | ||
|
||
use super::{Value, ValueError}; | ||
|
||
impl Value<i64> { | ||
pub fn get_value(&self) -> Result<i64> { | ||
let res = unsafe { metacall_value_to_long(self.ptr).to_owned() }; | ||
|
||
Ok(res) | ||
} | ||
} | ||
|
||
impl_value_constructor!( | ||
value => { | ||
let ptr = unsafe { metacall_value_create_long(value) }; | ||
|
||
check_null_ptr!(ptr, ValueError::NullPointer); | ||
|
||
Ok(Self { | ||
ptr, | ||
_phantom: PhantomData, | ||
}) | ||
}, i64 | ||
); | ||
|
||
impl Value<i32> { | ||
pub fn get_value(&self) -> Result<i32> { | ||
let res = unsafe { metacall_value_to_int(self.ptr).to_owned() }; | ||
|
||
Ok(res) | ||
} | ||
} | ||
|
||
impl Value<i16> { | ||
pub fn get_value(&self) -> Result<i16> { | ||
let res: i16 = unsafe { metacall_value_to_int(self.ptr).to_owned() }.try_into()?; | ||
|
||
Ok(res) | ||
} | ||
} | ||
|
||
impl_value_constructor!( | ||
value => { | ||
let ptr = unsafe { metacall_value_create_int(value.into()) }; | ||
|
||
check_null_ptr!(ptr, ValueError::NullPointer); | ||
|
||
Ok(Self { | ||
ptr, | ||
_phantom: PhantomData, | ||
}) | ||
}, i16, i32 | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
mod float; | ||
mod int; | ||
mod string; | ||
|
||
use anyhow::Result; | ||
use metacall_bindings::value::{ | ||
metacall_value_destroy, metacall_value_id, metacall_value_id_name, metacall_value_type_name, | ||
MetacallValueID, | ||
}; | ||
use std::{ | ||
ffi::{c_void, CStr}, | ||
marker::PhantomData, | ||
ptr::null_mut, | ||
}; | ||
use thiserror::Error; | ||
|
||
use crate::check_null_ptr; | ||
|
||
#[macro_export] | ||
macro_rules! impl_value_constructor { | ||
($value:ident => $code:block, $($type:ty),+) => { | ||
$( | ||
impl Value<$type> { | ||
pub fn new($value: $type) -> Result<Self> { | ||
$code | ||
} | ||
} | ||
)+ | ||
}; | ||
} | ||
|
||
#[derive(Error, Debug)] | ||
pub enum ValueError { | ||
#[error("Failed to create CString: {0}")] | ||
CStringError(#[from] std::ffi::NulError), | ||
#[error("Failed to convert CString to &str: {0}")] | ||
Utf8Error(#[from] std::str::Utf8Error), | ||
#[error("Null pointer encountered")] | ||
NullPointer, | ||
#[error("Unknown error")] | ||
Unknown, | ||
} | ||
|
||
pub struct Value<T> { | ||
ptr: *mut c_void, | ||
_phantom: PhantomData<T>, | ||
} | ||
|
||
impl<T> Value<T> { | ||
/// A simple method to check the nullity of the Value. | ||
pub fn is_null(&self) -> Result<bool> { | ||
let id = self.value_id()?; | ||
Ok(id == MetacallValueID::Null) | ||
} | ||
|
||
/// Provides the type identifier (ID). | ||
pub fn value_id(&self) -> Result<MetacallValueID> { | ||
check_null_ptr!(self.ptr, ValueError::NullPointer); | ||
let id = unsafe { metacall_value_id(self.ptr) }; | ||
Ok(id) | ||
} | ||
|
||
/// Provides the type identifier (ID) in a readable form (as a `String`). | ||
pub fn value_id_name(&self) -> Result<String> { | ||
check_null_ptr!(self.ptr, ValueError::NullPointer); | ||
let ptr = unsafe { metacall_value_type_name(self.ptr) }; | ||
let c_str = unsafe { CStr::from_ptr(ptr) }.to_str()?; | ||
Ok(c_str.to_string()) | ||
} | ||
} | ||
|
||
impl<T> Drop for Value<T> { | ||
fn drop(&mut self) { | ||
unsafe { | ||
metacall_value_destroy(self.ptr); | ||
self.ptr = null_mut(); | ||
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
|
||
use super::Value; | ||
#[test] | ||
fn metacall_create_value_string() { | ||
let string = String::from("Hello!"); | ||
let value = Value::<String>::new(string.clone()).unwrap(); | ||
let result = value.get_value().unwrap(); | ||
assert_eq!(result, string); | ||
println!("[String] \"{result}\" == \"{string}\" => Passed",); | ||
|
||
/* TODO(FIX): Error with &str | ||
thread 'value::test::metacall_create_value_str' panicked at src/value/mod.rs:96:9: | ||
assertion `left == right` failed | ||
left: "Hello!\"\u{7}" | ||
right: "Hello!" | ||
*/ | ||
let str = "Hello!"; | ||
let value = Value::<&str>::new(str).unwrap(); | ||
let result = value.get_value().unwrap(); | ||
assert_eq!(result, str); | ||
println!("[&str] \"{result}\" == \"{str}\" => Passed",); | ||
} | ||
|
||
#[test] | ||
fn metacall_create_value_int() { | ||
let int32 = i32::MAX; | ||
let value = Value::<i32>::new(int32).unwrap(); | ||
let result = value.get_value().unwrap(); | ||
assert_eq!(result, int32); | ||
println!("[i32] \"{result}\" == \"{int32}\" => Passed",); | ||
|
||
let int64 = i64::MAX; | ||
let value = Value::<i64>::new(int64).unwrap(); | ||
let result = value.get_value().unwrap(); | ||
assert_eq!(result, int64); | ||
println!("[i64] \"{result}\" == \"{int64}\" => Passed",); | ||
} | ||
|
||
#[test] | ||
fn metacall_create_value_float() { | ||
let float32 = f32::MAX; | ||
let value = Value::<f32>::new(float32).unwrap(); | ||
let result = value.get_value().unwrap(); | ||
assert_eq!(result, float32); | ||
println!("[i32] \"{result}\" == \"{float32}\" => Passed",); | ||
|
||
let float64 = f64::MAX; | ||
let value = Value::<f64>::new(float64).unwrap(); | ||
let result = value.get_value().unwrap(); | ||
assert_eq!(result, float64); | ||
println!("[i64] \"{result}\" == \"{float64}\" => Passed",); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
use std::{ffi::CStr, marker::PhantomData}; | ||
|
||
use anyhow::Result; | ||
use metacall_bindings::value::{create::metacall_value_create_string, metacall_value_to_string}; | ||
|
||
use crate::{check_null_ptr, impl_value_constructor}; | ||
|
||
use super::{Value, ValueError}; | ||
|
||
impl Value<&str> { | ||
pub fn get_value(&self) -> Result<&str> { | ||
let ptr = unsafe { metacall_value_to_string(self.ptr) }; | ||
|
||
check_null_ptr!(ptr, ValueError::NullPointer); | ||
|
||
let str = unsafe { CStr::from_ptr(ptr) }.to_str()?; | ||
Ok(str) | ||
} | ||
} | ||
|
||
impl Value<String> { | ||
pub fn get_value(&self) -> Result<String> { | ||
let ptr = unsafe { metacall_value_to_string(self.ptr) }; | ||
|
||
check_null_ptr!(ptr, ValueError::NullPointer); | ||
|
||
let str = unsafe { CStr::from_ptr(ptr) }.to_str()?; | ||
Ok(str.to_string()) | ||
} | ||
} | ||
|
||
impl_value_constructor!( | ||
value => { | ||
let ptr = | ||
unsafe { metacall_value_create_string(value.as_ptr() as *const i8, value.len() ) }; | ||
check_null_ptr!(ptr, ValueError::NullPointer); | ||
Ok(Self { | ||
ptr, | ||
_phantom: PhantomData, | ||
}) | ||
}, | ||
String, | ||
&str | ||
); |
Empty file.