1- use std:: ffi:: c_char;
1+ use std:: ffi:: { c_char, CString } ;
22use std:: sync:: Arc ;
33
4- use parking_lot:: Mutex ;
5-
64use mizer_runtime:: NodePreviewRef ;
75use mizer_util:: StructuredData ;
86
97use crate :: apis:: programmer:: FFIColorValue ;
108use crate :: apis:: transport:: Timecode ;
11- use crate :: pointer_inventory:: PointerInventory ;
129use crate :: types:: { drop_pointer, Array , FFIFromPointer } ;
1310
1411pub struct NodeHistory {
1512 preview_ref : NodePreviewRef ,
16- pointer_inventory : Mutex < PointerInventory > ,
1713}
1814
1915impl NodeHistory {
2016 pub fn new ( preview_ref : NodePreviewRef ) -> Self {
2117 Self {
2218 preview_ref,
23- pointer_inventory : Default :: default ( ) ,
2419 }
2520 }
2621
27- // TODO: This should probably drop old inventory after 2 generations
2822 fn convert ( & self , data : StructuredData ) -> FFIStructuredData {
29- let mut inventory = self . pointer_inventory . lock ( ) ;
30- convert_with_inventory ( data, & mut inventory)
31- }
32- }
33-
34- fn convert_with_inventory (
35- data : StructuredData ,
36- inventory : & mut PointerInventory ,
37- ) -> FFIStructuredData {
38- match data {
39- StructuredData :: Boolean ( bool) => FFIStructuredData :: boolean ( bool) ,
40- StructuredData :: Float ( float) => FFIStructuredData :: float ( float) ,
41- StructuredData :: Int ( int) => FFIStructuredData :: int ( int) ,
42- StructuredData :: Text ( text) => FFIStructuredData :: text ( inventory. allocate_string ( text) ) ,
43- StructuredData :: Array ( array) => FFIStructuredData :: array (
44- array
45- . into_iter ( )
46- . map ( |item| convert_with_inventory ( item, inventory) )
47- . collect ( ) ,
48- ) ,
49- StructuredData :: Object ( map) => FFIStructuredData :: object (
50- map. into_iter ( )
51- . map ( |( key, value) | FFIStructuredDataObjectEntry {
52- key : inventory. allocate_string ( key) ,
53- value : convert_with_inventory ( value, inventory) ,
54- } )
55- . collect ( ) ,
56- ) ,
57- StructuredData :: Null => FFIStructuredData :: null ( ) ,
23+ match data {
24+ StructuredData :: Boolean ( bool) => FFIStructuredData :: boolean ( bool) ,
25+ StructuredData :: Float ( float) => FFIStructuredData :: float ( float) ,
26+ StructuredData :: Int ( int) => FFIStructuredData :: int ( int) ,
27+ StructuredData :: Text ( text) => FFIStructuredData :: text ( CString :: new ( text) . unwrap_or_default ( ) . into_raw ( ) ) ,
28+ StructuredData :: Array ( array) => FFIStructuredData :: array (
29+ array
30+ . into_iter ( )
31+ . map ( |item| self . convert ( item) )
32+ . collect ( ) ,
33+ ) ,
34+ StructuredData :: Object ( map) => FFIStructuredData :: object (
35+ map. into_iter ( )
36+ . map ( |( key, value) | FFIStructuredDataObjectEntry {
37+ key : CString :: new ( key) . unwrap_or_default ( ) . into_raw ( ) ,
38+ value : self . convert ( value) ,
39+ } )
40+ . collect ( ) ,
41+ ) ,
42+ StructuredData :: Null => FFIStructuredData :: null ( ) ,
43+ }
5844 }
5945}
6046
@@ -66,7 +52,7 @@ pub struct FFIStructuredData {
6652}
6753
6854impl FFIStructuredData {
69- fn text ( text : * const c_char ) -> Self {
55+ fn text ( text : * mut c_char ) -> Self {
7056 Self {
7157 r#type : FFIStructuredDataType :: Text ,
7258 value : FFIStructuredDataValue { text } ,
@@ -118,6 +104,30 @@ impl FFIStructuredData {
118104 value : FFIStructuredDataValue { null : ( ) } ,
119105 }
120106 }
107+
108+ pub ( crate ) fn as_array ( & self ) -> Option < Array < FFIStructuredData > > {
109+ if let FFIStructuredDataType :: Array = self . r#type {
110+ Some ( unsafe { self . value . array } )
111+ } else {
112+ None
113+ }
114+ }
115+
116+ pub ( crate ) fn as_object ( & self ) -> Option < Array < FFIStructuredDataObjectEntry > > {
117+ if let FFIStructuredDataType :: Object = self . r#type {
118+ Some ( unsafe { self . value . object } )
119+ } else {
120+ None
121+ }
122+ }
123+
124+ pub ( crate ) fn as_text ( & self ) -> Option < CString > {
125+ if let FFIStructuredDataType :: Text = self . r#type {
126+ Some ( unsafe { CString :: from_raw ( self . value . text ) } )
127+ } else {
128+ None
129+ }
130+ }
121131}
122132
123133#[ derive( Clone , Copy ) ]
@@ -135,7 +145,7 @@ pub enum FFIStructuredDataType {
135145#[ derive( Clone , Copy ) ]
136146#[ repr( C ) ]
137147pub union FFIStructuredDataValue {
138- pub text : * const c_char ,
148+ pub text : * mut c_char ,
139149 pub floating_point : f64 ,
140150 pub integer : i64 ,
141151 pub boolean : u8 ,
@@ -147,7 +157,7 @@ pub union FFIStructuredDataValue {
147157#[ derive( Clone , Copy ) ]
148158#[ repr( C ) ]
149159pub struct FFIStructuredDataObjectEntry {
150- pub key : * const c_char ,
160+ pub key : * mut c_char ,
151161 pub value : FFIStructuredData ,
152162}
153163
@@ -215,3 +225,22 @@ pub extern "C" fn read_node_multi_preview(ptr: *const NodeHistory) -> Array<f64>
215225
216226 values. into ( )
217227}
228+
229+ #[ no_mangle]
230+ pub extern "C" fn drop_structured_data ( data : FFIStructuredData ) {
231+ if let Some ( array) = data. as_array ( ) {
232+ let vec = array. into_vec ( ) ;
233+ for item in vec {
234+ drop_structured_data ( item) ;
235+ }
236+ } else if let Some ( object) = data. as_object ( ) {
237+ let vec = object. into_vec ( ) ;
238+ for item in vec {
239+ let key = unsafe { CString :: from_raw ( item. key ) } ;
240+ drop ( key) ;
241+ drop_structured_data ( item. value ) ;
242+ }
243+ } else if let Some ( text) = data. as_text ( ) {
244+ drop ( text)
245+ }
246+ }
0 commit comments