use std::ptr;
use crate::abi::{
cj_bytes_list_t, cj_bytes_t, cj_cityobject_draft_t, cj_contact_t, cj_geometry_boundary_t,
cj_geometry_draft_t, cj_geometry_types_t, cj_indices_t, cj_model_selection_t, cj_model_t,
cj_ring_draft_t, cj_shell_draft_t, cj_solid_draft_t, cj_surface_draft_t, cj_uv_t, cj_uvs_t,
cj_value_t, cj_vertex_t, cj_vertices_t,
};
use crate::authoring::{
GeometryAuthoring, OwnedCityObject, OwnedContact, OwnedValue, RingAuthoring, ShellAuthoring,
SolidAuthoring, SurfaceAuthoring,
};
pub fn model_into_handle(model: cityjson_lib::CityModel) -> *mut cj_model_t {
Box::into_raw(Box::new(model)).cast::<cj_model_t>()
}
pub unsafe fn model_take(handle: *mut cj_model_t) -> Option<Box<cityjson_lib::CityModel>> {
if handle.is_null() {
return None;
}
Some(unsafe { Box::from_raw(handle.cast::<cityjson_lib::CityModel>()) })
}
pub unsafe fn model_as_ref<'a>(handle: *const cj_model_t) -> Option<&'a cityjson_lib::CityModel> {
unsafe { handle.cast::<cityjson_lib::CityModel>().as_ref() }
}
pub unsafe fn model_as_mut<'a>(handle: *mut cj_model_t) -> Option<&'a mut cityjson_lib::CityModel> {
unsafe { handle.cast::<cityjson_lib::CityModel>().as_mut() }
}
pub unsafe fn model_free(handle: *mut cj_model_t) {
let _ = unsafe { model_take(handle) };
}
pub fn model_selection_into_handle(
selection: cityjson_lib::ops::ModelSelection,
) -> *mut cj_model_selection_t {
Box::into_raw(Box::new(selection)).cast::<cj_model_selection_t>()
}
pub unsafe fn model_selection_take(
handle: *mut cj_model_selection_t,
) -> Option<Box<cityjson_lib::ops::ModelSelection>> {
if handle.is_null() {
return None;
}
Some(unsafe { Box::from_raw(handle.cast::<cityjson_lib::ops::ModelSelection>()) })
}
pub unsafe fn model_selection_as_ref<'a>(
handle: *const cj_model_selection_t,
) -> Option<&'a cityjson_lib::ops::ModelSelection> {
unsafe { handle.cast::<cityjson_lib::ops::ModelSelection>().as_ref() }
}
pub unsafe fn model_selection_free(handle: *mut cj_model_selection_t) {
let _ = unsafe { model_selection_take(handle) };
}
macro_rules! define_handle_accessors {
($into_fn:ident, $take_fn:ident, $as_mut_fn:ident, $free_fn:ident, $ffi_ty:ty, $rust_ty:ty) => {
pub fn $into_fn(value: $rust_ty) -> *mut $ffi_ty {
Box::into_raw(Box::new(value)).cast::<$ffi_ty>()
}
pub unsafe fn $take_fn(handle: *mut $ffi_ty) -> Option<Box<$rust_ty>> {
if handle.is_null() {
return None;
}
Some(unsafe { Box::from_raw(handle.cast::<$rust_ty>()) })
}
pub unsafe fn $as_mut_fn<'a>(handle: *mut $ffi_ty) -> Option<&'a mut $rust_ty> {
unsafe { handle.cast::<$rust_ty>().as_mut() }
}
pub unsafe fn $free_fn(handle: *mut $ffi_ty) {
let _ = unsafe { $take_fn(handle) };
}
};
}
define_handle_accessors!(
value_into_handle,
value_take,
value_as_mut,
value_free,
cj_value_t,
OwnedValue
);
define_handle_accessors!(
contact_into_handle,
contact_take,
contact_as_mut,
contact_free,
cj_contact_t,
OwnedContact
);
define_handle_accessors!(
cityobject_draft_into_handle,
cityobject_draft_take,
cityobject_draft_as_mut,
cityobject_draft_free,
cj_cityobject_draft_t,
OwnedCityObject
);
define_handle_accessors!(
ring_draft_into_handle,
ring_draft_take,
ring_draft_as_mut,
ring_draft_free,
cj_ring_draft_t,
RingAuthoring
);
define_handle_accessors!(
surface_draft_into_handle,
surface_draft_take,
surface_draft_as_mut,
surface_draft_free,
cj_surface_draft_t,
SurfaceAuthoring
);
define_handle_accessors!(
shell_draft_into_handle,
shell_draft_take,
shell_draft_as_mut,
shell_draft_free,
cj_shell_draft_t,
ShellAuthoring
);
define_handle_accessors!(
solid_draft_into_handle,
solid_draft_take,
solid_draft_as_mut,
solid_draft_free,
cj_solid_draft_t,
SolidAuthoring
);
define_handle_accessors!(
geometry_draft_into_handle,
geometry_draft_take,
geometry_draft_as_mut,
geometry_draft_free,
cj_geometry_draft_t,
GeometryAuthoring
);
pub fn bytes_from_vec(bytes: Vec<u8>) -> cj_bytes_t {
let boxed = bytes.into_boxed_slice();
let len = boxed.len();
let data = Box::into_raw(boxed).cast::<u8>();
cj_bytes_t { data, len }
}
pub fn bytes_from_string(bytes: String) -> cj_bytes_t {
bytes_from_vec(bytes.into_bytes())
}
pub fn bytes_list_from_vec(bytes: Vec<cj_bytes_t>) -> cj_bytes_list_t {
let boxed = bytes.into_boxed_slice();
let len = boxed.len();
let data = Box::into_raw(boxed).cast::<cj_bytes_t>();
cj_bytes_list_t { data, len }
}
pub fn vertices_from_vec(vertices: Vec<cj_vertex_t>) -> cj_vertices_t {
let boxed = vertices.into_boxed_slice();
let len = boxed.len();
let data = Box::into_raw(boxed).cast::<cj_vertex_t>();
cj_vertices_t { data, len }
}
pub fn geometry_types_from_vec(types: Vec<crate::abi::cj_geometry_type_t>) -> cj_geometry_types_t {
let boxed = types.into_boxed_slice();
let len = boxed.len();
let data = Box::into_raw(boxed).cast::<crate::abi::cj_geometry_type_t>();
cj_geometry_types_t { data, len }
}
pub fn uvs_from_vec(uvs: Vec<cj_uv_t>) -> cj_uvs_t {
let boxed = uvs.into_boxed_slice();
let len = boxed.len();
let data = Box::into_raw(boxed).cast::<cj_uv_t>();
cj_uvs_t { data, len }
}
pub fn indices_from_vec(indices: Vec<usize>) -> cj_indices_t {
let boxed = indices.into_boxed_slice();
let len = boxed.len();
let data = Box::into_raw(boxed).cast::<usize>();
cj_indices_t { data, len }
}
pub unsafe fn bytes_free(bytes: cj_bytes_t) {
if bytes.data.is_null() {
return;
}
let slice = ptr::slice_from_raw_parts_mut(bytes.data, bytes.len);
unsafe {
drop(Box::from_raw(slice));
}
}
pub unsafe fn bytes_list_free(bytes: cj_bytes_list_t) {
if bytes.data.is_null() {
return;
}
let slice = ptr::slice_from_raw_parts_mut(bytes.data, bytes.len);
unsafe {
for item in &*slice {
bytes_free(*item);
}
drop(Box::from_raw(slice));
}
}
pub unsafe fn vertices_free(vertices: cj_vertices_t) {
if vertices.data.is_null() {
return;
}
let slice = ptr::slice_from_raw_parts_mut(vertices.data, vertices.len);
unsafe {
drop(Box::from_raw(slice));
}
}
pub unsafe fn uvs_free(uvs: cj_uvs_t) {
if uvs.data.is_null() {
return;
}
let slice = ptr::slice_from_raw_parts_mut(uvs.data, uvs.len);
unsafe {
drop(Box::from_raw(slice));
}
}
pub unsafe fn indices_free(indices: cj_indices_t) {
if indices.data.is_null() {
return;
}
let slice = ptr::slice_from_raw_parts_mut(indices.data, indices.len);
unsafe {
drop(Box::from_raw(slice));
}
}
pub unsafe fn geometry_types_free(types: cj_geometry_types_t) {
if types.data.is_null() {
return;
}
let slice = ptr::slice_from_raw_parts_mut(types.data, types.len);
unsafe {
drop(Box::from_raw(slice));
}
}
pub unsafe fn geometry_boundary_free(boundary: cj_geometry_boundary_t) {
unsafe {
indices_free(boundary.vertex_indices);
indices_free(boundary.ring_offsets);
indices_free(boundary.surface_offsets);
indices_free(boundary.shell_offsets);
indices_free(boundary.solid_offsets);
}
}