@@ -51,7 +51,7 @@ def __init__(self):
5151
5252 def add_line (self , text : str = "" ):
5353 if text .strip ():
54- self .lines .append (" " * self .indent_level + text )
54+ self .lines .append (" " * self .indent_level + text )
5555 else :
5656 self .lines .append ("" )
5757
@@ -62,15 +62,14 @@ def dedent(self):
6262 self .indent_level = max (0 , self .indent_level - 1 )
6363
6464 def add_block (self , header : str , content_func ):
65- self .add_line (header )
66- self .add_line ("{" )
65+ self .add_line (header + " {" )
6766 self .indent ()
6867 content_func ()
6968 self .dedent ()
7069 self .add_line ("}" )
7170
7271 def get_code (self ) -> str :
73- return "\r \ n " .join (self .lines )
72+ return "\n " .join (self .lines )
7473
7574
7675def split_by_last_dot (value : str ):
@@ -95,6 +94,7 @@ def parse_native(lines: list[str]):
9594 writer .add_line ("#pragma warning disable CS0649" )
9695 writer .add_line ("#pragma warning disable CS0169" )
9796 writer .add_line ()
97+ writer .add_line ("using System.Buffers;" )
9898 writer .add_line ("using System.Text;" )
9999 writer .add_line ("using System.Threading;" )
100100 writer .add_line ("using SwiftlyS2.Shared.Natives;" )
@@ -158,68 +158,24 @@ def write_method_content():
158158 if is_marked_sync :
159159 writer .add_block ("if (Thread.CurrentThread.ManagedThreadId != _MainThreadID)" , lambda : writer .add_line ('throw new InvalidOperationException("This method can only be called from the main thread.");' ))
160160
161- string_params = [n for t , n in param_signatures if t == "string" ]
162- bytes_params = [n for t , n in param_signatures if t == "byte[]" ]
163-
164- for param in bytes_params :
165- writer .add_line (f"var { param } Length = { param } .Length;" )
166-
167- if not string_params :
168- fixed_blocks = []
169- for param in bytes_params :
170- fixed_blocks .append (f"fixed (byte* { param } BufferPtr = { param } )" )
171-
172- def write_simple_call ():
173- call_args = []
174- for t , n in param_signatures :
175- if t == "byte[]" :
176- call_args .extend ([f"{ n } BufferPtr" , f"{ n } Length" ])
177- elif t == "bool" :
178- call_args .append (f"{ n } ? (byte)1 : (byte)0" )
179- else :
180- call_args .append (n )
181-
182- if is_buffer_return (return_type ):
183- first_call_args = ["null" ] + call_args
184- writer .add_line (f"var ret = _{ function_name } ({ ', ' .join (first_call_args )} );" )
185- if return_type == "string" :
186- writer .add_line ("var retBuffer = new byte[ret + 1];" )
187- else :
188- writer .add_line ("var retBuffer = new byte[ret];" )
189-
190- def write_ret_fixed ():
191- second_call_args = ["retBufferPtr" ] + call_args
192- writer .add_line (f"ret = _{ function_name } ({ ', ' .join (second_call_args )} );" )
193- if return_type == "string" :
194- writer .add_line ("return Encoding.UTF8.GetString(retBufferPtr, ret);" )
195- else :
196- writer .add_line ("var retBytes = new byte[ret];" )
197- writer .add_line ("for (int i = 0; i < ret; i++) retBytes[i] = retBufferPtr[i];" )
198- writer .add_line ("return retBytes;" )
199-
200- writer .add_block ("fixed (byte* retBufferPtr = retBuffer)" , write_ret_fixed )
201- else :
202- if return_type == "void" :
203- writer .add_line (f"_{ function_name } ({ ', ' .join (call_args )} );" )
204- else :
205- writer .add_line (f"var ret = _{ function_name } ({ ', ' .join (call_args )} );" )
206- writer .add_line ("return ret == 1;" if return_type == "bool" else "return ret;" )
207-
208- def write_with_fixed_blocks (blocks , index = 0 ):
209- if index < len (blocks ):
210- writer .add_block (blocks [index ], lambda : write_with_fixed_blocks (blocks , index + 1 ))
211- else :
212- write_simple_call ()
213-
214- if fixed_blocks :
215- write_with_fixed_blocks (fixed_blocks )
216- else :
217- write_simple_call ()
218- return
219-
220- for param in string_params :
221- writer .add_line (f"byte[] { param } Buffer = Encoding.UTF8.GetBytes({ param } + \" \\ 0\" );" )
161+ string_params = []
162+ bytes_params = []
163+ pool_declared = False
222164
165+ for t , n in param_signatures :
166+ if t == "string" :
167+ if not pool_declared :
168+ writer .add_line ("var pool = ArrayPool<byte>.Shared;" )
169+ pool_declared = True
170+ writer .add_line (f"var { n } Length = Encoding.UTF8.GetByteCount({ n } );" )
171+ writer .add_line (f"var { n } Buffer = pool.Rent({ n } Length + 1);" )
172+ writer .add_line (f"Encoding.UTF8.GetBytes({ n } , { n } Buffer);" )
173+ writer .add_line (f"{ n } Buffer[{ n } Length] = 0;" )
174+ string_params .append (n )
175+ elif t == "byte[]" :
176+ writer .add_line (f"var { n } Length = { n } .Length;" )
177+ bytes_params .append (n )
178+
223179 fixed_blocks = []
224180 for param in string_params :
225181 fixed_blocks .append (f"fixed (byte* { param } BufferPtr = { param } Buffer)" )
@@ -228,42 +184,77 @@ def write_with_fixed_blocks(blocks, index=0):
228184
229185 def write_native_call ():
230186 call_args = []
231- for t , n in param_signatures :
232- if t == "string" :
233- call_args .append (f"{ n } BufferPtr" )
234- elif t == "byte[]" :
235- call_args .extend ([f"{ n } BufferPtr" , f"{ n } Length" ])
236- elif t == "bool" :
237- call_args .append (f"{ n } ? (byte)1 : (byte)0" )
238- else :
239- call_args .append (n )
240187
241188 if is_buffer_return (return_type ):
242- first_call_args = ["null" ] + call_args
189+ first_call_args = ["null" ]
190+ for t , n in param_signatures :
191+ if t == "string" :
192+ first_call_args .append (f"{ n } BufferPtr" )
193+ elif t == "byte[]" :
194+ first_call_args .extend ([f"{ n } BufferPtr" , f"{ n } Length" ])
195+ elif t == "bool" :
196+ first_call_args .append (f"{ n } ? (byte)1 : (byte)0" )
197+ else :
198+ first_call_args .append (n )
199+
243200 writer .add_line (f"var ret = _{ function_name } ({ ', ' .join (first_call_args )} );" )
244- if return_type == "string" :
245- writer . add_line ( "var retBuffer = new byte[ret + 1];" )
246- else :
247- writer .add_line ("var retBuffer = new byte[ ret] ;" )
201+
202+ if not pool_declared :
203+ writer . add_line ( "var pool = ArrayPool<byte>.Shared;" )
204+ writer .add_line ("var retBuffer = pool.Rent( ret + 1) ;" )
248205
249206 def write_ret_fixed ():
250- second_call_args = ["retBufferPtr" ] + call_args
207+ second_call_args = ["retBufferPtr" ]
208+ for t , n in param_signatures :
209+ if t == "string" :
210+ second_call_args .append (f"{ n } BufferPtr" )
211+ elif t == "byte[]" :
212+ second_call_args .extend ([f"{ n } BufferPtr" , f"{ n } Length" ])
213+ elif t == "bool" :
214+ second_call_args .append (f"{ n } ? (byte)1 : (byte)0" )
215+ else :
216+ second_call_args .append (n )
217+
251218 writer .add_line (f"ret = _{ function_name } ({ ', ' .join (second_call_args )} );" )
219+
252220 if return_type == "string" :
253- writer .add_line ("return Encoding.UTF8.GetString(retBufferPtr, ret);" )
221+ writer .add_line ("var retString = Encoding.UTF8.GetString(retBufferPtr, ret);" )
222+ writer .add_line ("pool.Return(retBuffer);" )
223+ for param in string_params :
224+ writer .add_line (f"pool.Return({ param } Buffer);" )
225+ writer .add_line ("return retString;" )
254226 else :
255227 writer .add_line ("var retBytes = new byte[ret];" )
256228 writer .add_line ("for (int i = 0; i < ret; i++) retBytes[i] = retBufferPtr[i];" )
229+ writer .add_line ("pool.Return(retBuffer);" )
230+ for param in string_params :
231+ writer .add_line (f"pool.Return({ param } Buffer);" )
257232 writer .add_line ("return retBytes;" )
258233
259234 writer .add_block ("fixed (byte* retBufferPtr = retBuffer)" , write_ret_fixed )
235+
260236 else :
237+ for t , n in param_signatures :
238+ if t == "string" :
239+ call_args .append (f"{ n } BufferPtr" )
240+ elif t == "byte[]" :
241+ call_args .extend ([f"{ n } BufferPtr" , f"{ n } Length" ])
242+ elif t == "bool" :
243+ call_args .append (f"{ n } ? (byte)1 : (byte)0" )
244+ else :
245+ call_args .append (n )
246+
261247 if return_type == "void" :
262248 writer .add_line (f"_{ function_name } ({ ', ' .join (call_args )} );" )
263249 else :
264250 writer .add_line (f"var ret = _{ function_name } ({ ', ' .join (call_args )} );" )
265- writer .add_line ("return ret == 1;" if return_type == "bool" else "return ret;" )
266-
251+
252+ for param in string_params :
253+ writer .add_line (f"pool.Return({ param } Buffer);" )
254+
255+ if return_type != "void" :
256+ writer .add_line ("return ret == 1;" if return_type == "bool" else f"return ret;" )
257+
267258 def write_with_fixed_blocks (blocks , index = 0 ):
268259 if index < len (blocks ):
269260 writer .add_block (blocks [index ], lambda : write_with_fixed_blocks (blocks , index + 1 ))
@@ -276,10 +267,7 @@ def write_with_fixed_blocks(blocks, index=0):
276267 write_native_call ()
277268
278269 writer .add_block (f"public unsafe static { RETURN_TYPE_MAP [return_type ]} { function_name } ({ method_signature } )" , write_method_content )
279-
280- # Benchmark class should be public for external access
281- access_modifier = "public" if class_name == "Benchmark" else "internal"
282- writer .add_block (f"{ access_modifier } static class Native{ class_name } " , write_class_content )
270+ writer .add_block (f"internal static class Native{ class_name } " , write_class_content )
283271
284272 with open (out_path , "w" , encoding = "utf-8" , newline = "" ) as f :
285273 f .write (writer .get_code ())
0 commit comments