Rust structs are always treated as pointers by SWIG. However, a rust API can take values by value, by reference, or by pointer. When annotating your api, you can use Struct.type to pass by value, Struct.type.ref() to pass by (mutable) reference, etc. Note that this is only for defini
| 3 | from .function import Function, Method |
| 4 | |
| 5 | class StructType(Type): |
| 6 | '''Rust structs are always treated as pointers by SWIG. |
| 7 | However, a rust API can take values by value, by reference, or by pointer. |
| 8 | When annotating your api, you can use Struct.type to pass by value, |
| 9 | Struct.type.ref() to pass by (mutable) reference, etc. |
| 10 | Note that this is only for defining the types of structs, the actual struct codegen |
| 11 | is in StructWrapper.''' |
| 12 | |
| 13 | RUST_BY_VALUE = 0 |
| 14 | RUST_REF = 1 |
| 15 | RUST_MUT_REF = 2 |
| 16 | |
| 17 | def __init__(self, wrapper, kind=0): |
| 18 | self.wrapper = wrapper |
| 19 | super(StructType, self).__init__( |
| 20 | '*mut '+wrapper.module+'::'+unturbofish(wrapper.name), |
| 21 | wrapper.c_name+'*', |
| 22 | sanitize_rust_name(wrapper.name), |
| 23 | default='0 as *mut _' |
| 24 | ) |
| 25 | self.kind = kind |
| 26 | |
| 27 | def ref(self): |
| 28 | '''Mutable references coerce to non-mutable references, and the |
| 29 | types in the C API are the same.''' |
| 30 | return StructType(self.wrapper, kind=StructType.RUST_MUT_REF) |
| 31 | |
| 32 | def mut_ref(self): |
| 33 | return StructType(self.wrapper, kind=StructType.RUST_MUT_REF) |
| 34 | |
| 35 | def wrap_c_value(self, name): |
| 36 | pre_check = f'let _{name} = check_null!({name}, _default);' |
| 37 | if self.kind == StructType.RUST_BY_VALUE: |
| 38 | value = f'_{name}.clone()' |
| 39 | elif self.kind == StructType.RUST_MUT_REF: |
| 40 | value = f'_{name}' |
| 41 | else: |
| 42 | raise Exception(f'Unknown pointer type: {self.kind}') |
| 43 | return (pre_check, value, '') |
| 44 | |
| 45 | def unwrap_rust_value(self, name): |
| 46 | if self.kind == StructType.RUST_BY_VALUE: |
| 47 | result = name |
| 48 | elif self.kind == StructType.RUST_MUT_REF: |
| 49 | # if a rust function returns a reference, we just clone it :/ |
| 50 | # It's The Only Way To Be Sure |
| 51 | result = f'{name}.clone()' |
| 52 | |
| 53 | return f'Box::into_raw(Box::new(borrow_check({result})))' |
| 54 | |
| 55 | def wrap_python_value(self, name): |
| 56 | return f'{name}._ptr' |
| 57 | |
| 58 | def python_postfix(self): |
| 59 | pyname = sanitize_rust_name(self.wrapper.name) |
| 60 | return s(f'''\ |
| 61 | _result = {pyname}.__new__({pyname}) |
| 62 | if result != _ffi.NULL: |