Merge pull request #44 from TheBlueMatt/main
[ldk-c-bindings] / lightning-c-bindings / src / c_types / mod.rs
1 //! This module contains standard C-mapped types for types not in the original crate.
2
3 /// Auto-generated C-mapped types for templated containers
4 pub mod derived;
5
6 use bitcoin::Transaction as BitcoinTransaction;
7 use bitcoin::hashes::Hash;
8 use bitcoin::secp256k1::key::PublicKey as SecpPublicKey;
9 use bitcoin::secp256k1::key::SecretKey as SecpSecretKey;
10 use bitcoin::secp256k1::Signature as SecpSignature;
11 use bitcoin::secp256k1::Error as SecpError;
12 use bitcoin::secp256k1::recovery::RecoveryId;
13 use bitcoin::secp256k1::recovery::RecoverableSignature as SecpRecoverableSignature;
14 use bitcoin::bech32;
15
16 use std::convert::TryInto; // Bindings need at least rustc 1.34
17
18 use std::io::{Cursor, Read}; // TODO: We should use core2 here when we support no_std
19
20 #[repr(C)]
21 /// A dummy struct of which an instance must never exist.
22 /// This corresponds to the Rust type `Infallible`, or, in unstable rust, `!`
23 pub struct NotConstructable {
24         _priv_thing: core::convert::Infallible,
25 }
26 impl From<core::convert::Infallible> for NotConstructable {
27         fn from(_: core::convert::Infallible) -> Self { unreachable!(); }
28 }
29
30 /// Integer in the range `0..32`
31 #[derive(PartialEq, Eq, Copy, Clone)]
32 #[allow(non_camel_case_types)]
33 #[repr(C)]
34 pub struct u5(u8);
35
36 impl From<bech32::u5> for u5 {
37         fn from(o: bech32::u5) -> Self { Self(o.to_u8()) }
38 }
39 impl Into<bech32::u5> for u5 {
40         fn into(self) -> bech32::u5 { bech32::u5::try_from_u8(self.0).expect("u5 objects must be in the range 0..32") }
41 }
42
43 #[derive(Clone)]
44 #[repr(C)]
45 /// Represents a valid secp256k1 public key serialized in "compressed form" as a 33 byte array.
46 pub struct PublicKey {
47         /// The bytes of the public key
48         pub compressed_form: [u8; 33],
49 }
50 impl PublicKey {
51         pub(crate) fn from_rust(pk: &SecpPublicKey) -> Self {
52                 Self {
53                         compressed_form: pk.serialize(),
54                 }
55         }
56         pub(crate) fn into_rust(&self) -> SecpPublicKey {
57                 SecpPublicKey::from_slice(&self.compressed_form).unwrap()
58         }
59         pub(crate) fn is_null(&self) -> bool { self.compressed_form[..] == [0; 33][..] }
60         pub(crate) fn null() -> Self { Self { compressed_form: [0; 33] } }
61 }
62
63 #[repr(C)]
64 /// Represents a valid secp256k1 secret key serialized as a 32 byte array.
65 pub struct SecretKey {
66         /// The bytes of the secret key
67         pub bytes: [u8; 32],
68 }
69 impl SecretKey {
70         // from_rust isn't implemented for a ref since we just return byte array refs directly
71         pub(crate) fn from_rust(sk: SecpSecretKey) -> Self {
72                 let mut bytes = [0; 32];
73                 bytes.copy_from_slice(&sk[..]);
74                 Self { bytes }
75         }
76         pub(crate) fn into_rust(&self) -> SecpSecretKey {
77                 SecpSecretKey::from_slice(&self.bytes).unwrap()
78         }
79 }
80
81 #[repr(C)]
82 #[derive(Clone)]
83 /// Represents a secp256k1 signature serialized as two 32-byte numbers
84 pub struct Signature {
85         /// The bytes of the signature in "compact" form
86         pub compact_form: [u8; 64],
87 }
88 impl Signature {
89         pub(crate) fn from_rust(pk: &SecpSignature) -> Self {
90                 Self {
91                         compact_form: pk.serialize_compact(),
92                 }
93         }
94         pub(crate) fn into_rust(&self) -> SecpSignature {
95                 SecpSignature::from_compact(&self.compact_form).unwrap()
96         }
97         // The following are used for Option<Signature> which we support, but don't use anymore
98         #[allow(unused)] pub(crate) fn is_null(&self) -> bool { self.compact_form[..] == [0; 64][..] }
99         #[allow(unused)] pub(crate) fn null() -> Self { Self { compact_form: [0; 64] } }
100 }
101
102 #[repr(C)]
103 #[derive(Clone)]
104 /// Represents a secp256k1 signature serialized as two 32-byte numbers as well as a tag which
105 /// allows recovering the exact public key which created the signature given the message.
106 pub struct RecoverableSignature {
107         /// The bytes of the signature in "compact" form plus a "Recovery ID" which allows for
108         /// recovery.
109         pub serialized_form: [u8; 68],
110 }
111 impl RecoverableSignature {
112         pub(crate) fn from_rust(pk: &SecpRecoverableSignature) -> Self {
113                 let (id, compact_form) = pk.serialize_compact();
114                 let mut serialized_form = [0; 68];
115                 serialized_form[0..64].copy_from_slice(&compact_form[..]);
116                 serialized_form[64..].copy_from_slice(&id.to_i32().to_le_bytes());
117                 Self { serialized_form }
118         }
119         pub(crate) fn into_rust(&self) -> SecpRecoverableSignature {
120                 let mut id = [0; 4];
121                 id.copy_from_slice(&self.serialized_form[64..]);
122                 SecpRecoverableSignature::from_compact(&self.serialized_form[0..64],
123                                 RecoveryId::from_i32(i32::from_le_bytes(id)).expect("Invalid Recovery ID"))
124                         .unwrap()
125         }
126 }
127
128 #[repr(C)]
129 #[derive(Copy, Clone)]
130 /// Represents an error returned from libsecp256k1 during validation of some secp256k1 data
131 pub enum Secp256k1Error {
132         /// Signature failed verification
133         IncorrectSignature,
134         /// Badly sized message ("messages" are actually fixed-sized digests; see the MESSAGE_SIZE constant)
135         InvalidMessage,
136         /// Bad public key
137         InvalidPublicKey,
138         /// Bad signature
139         InvalidSignature,
140         /// Bad secret key
141         InvalidSecretKey,
142         /// Bad recovery id
143         InvalidRecoveryId,
144         /// Invalid tweak for add_assign or mul_assign
145         InvalidTweak,
146         /// tweak_add_check failed on an xonly public key
147         TweakCheckFailed,
148         /// Didn't pass enough memory to context creation with preallocated memory
149         NotEnoughMemory,
150 }
151 impl Secp256k1Error {
152         pub(crate) fn from_rust(err: SecpError) -> Self {
153                 match err {
154                         SecpError::IncorrectSignature => Secp256k1Error::IncorrectSignature,
155                         SecpError::InvalidMessage => Secp256k1Error::InvalidMessage,
156                         SecpError::InvalidPublicKey => Secp256k1Error::InvalidPublicKey,
157                         SecpError::InvalidSignature => Secp256k1Error::InvalidSignature,
158                         SecpError::InvalidSecretKey => Secp256k1Error::InvalidSecretKey,
159                         SecpError::InvalidRecoveryId => Secp256k1Error::InvalidRecoveryId,
160                         SecpError::InvalidTweak => Secp256k1Error::InvalidTweak,
161                         SecpError::TweakCheckFailed => Secp256k1Error::TweakCheckFailed,
162                         SecpError::NotEnoughMemory => Secp256k1Error::NotEnoughMemory,
163                 }
164         }
165 }
166
167 #[repr(C)]
168 #[allow(missing_docs)] // If there's no docs upstream, that's good enough for us
169 #[derive(Clone, Copy, PartialEq)]
170 /// Represents an IO Error. Note that some information is lost in the conversion from Rust.
171 pub enum IOError {
172         NotFound,
173         PermissionDenied,
174         ConnectionRefused,
175         ConnectionReset,
176         ConnectionAborted,
177         NotConnected,
178         AddrInUse,
179         AddrNotAvailable,
180         BrokenPipe,
181         AlreadyExists,
182         WouldBlock,
183         InvalidInput,
184         InvalidData,
185         TimedOut,
186         WriteZero,
187         Interrupted,
188         Other,
189         UnexpectedEof,
190 }
191 impl IOError {
192         pub(crate) fn from_rust(err: std::io::Error) -> Self {
193                 match err.kind() {
194                         std::io::ErrorKind::NotFound => IOError::NotFound,
195                         std::io::ErrorKind::PermissionDenied => IOError::PermissionDenied,
196                         std::io::ErrorKind::ConnectionRefused => IOError::ConnectionRefused,
197                         std::io::ErrorKind::ConnectionReset => IOError::ConnectionReset,
198                         std::io::ErrorKind::ConnectionAborted => IOError::ConnectionAborted,
199                         std::io::ErrorKind::NotConnected => IOError::NotConnected,
200                         std::io::ErrorKind::AddrInUse => IOError::AddrInUse,
201                         std::io::ErrorKind::AddrNotAvailable => IOError::AddrNotAvailable,
202                         std::io::ErrorKind::BrokenPipe => IOError::BrokenPipe,
203                         std::io::ErrorKind::AlreadyExists => IOError::AlreadyExists,
204                         std::io::ErrorKind::WouldBlock => IOError::WouldBlock,
205                         std::io::ErrorKind::InvalidInput => IOError::InvalidInput,
206                         std::io::ErrorKind::InvalidData => IOError::InvalidData,
207                         std::io::ErrorKind::TimedOut => IOError::TimedOut,
208                         std::io::ErrorKind::WriteZero => IOError::WriteZero,
209                         std::io::ErrorKind::Interrupted => IOError::Interrupted,
210                         std::io::ErrorKind::Other => IOError::Other,
211                         std::io::ErrorKind::UnexpectedEof => IOError::UnexpectedEof,
212                         _ => IOError::Other,
213                 }
214         }
215         pub(crate) fn to_rust(&self) -> std::io::Error {
216                 std::io::Error::new(match self {
217                         IOError::NotFound => std::io::ErrorKind::NotFound,
218                         IOError::PermissionDenied => std::io::ErrorKind::PermissionDenied,
219                         IOError::ConnectionRefused => std::io::ErrorKind::ConnectionRefused,
220                         IOError::ConnectionReset => std::io::ErrorKind::ConnectionReset,
221                         IOError::ConnectionAborted => std::io::ErrorKind::ConnectionAborted,
222                         IOError::NotConnected => std::io::ErrorKind::NotConnected,
223                         IOError::AddrInUse => std::io::ErrorKind::AddrInUse,
224                         IOError::AddrNotAvailable => std::io::ErrorKind::AddrNotAvailable,
225                         IOError::BrokenPipe => std::io::ErrorKind::BrokenPipe,
226                         IOError::AlreadyExists => std::io::ErrorKind::AlreadyExists,
227                         IOError::WouldBlock => std::io::ErrorKind::WouldBlock,
228                         IOError::InvalidInput => std::io::ErrorKind::InvalidInput,
229                         IOError::InvalidData => std::io::ErrorKind::InvalidData,
230                         IOError::TimedOut => std::io::ErrorKind::TimedOut,
231                         IOError::WriteZero => std::io::ErrorKind::WriteZero,
232                         IOError::Interrupted => std::io::ErrorKind::Interrupted,
233                         IOError::Other => std::io::ErrorKind::Other,
234                         IOError::UnexpectedEof => std::io::ErrorKind::UnexpectedEof,
235                 }, "")
236         }
237 }
238
239 #[repr(C)]
240 /// A serialized transaction, in (pointer, length) form.
241 ///
242 /// This type optionally owns its own memory, and thus the semantics around access change based on
243 /// the `data_is_owned` flag. If `data_is_owned` is set, you must call `Transaction_free` to free
244 /// the underlying buffer before the object goes out of scope. If `data_is_owned` is not set, any
245 /// access to the buffer after the scope in which the object was provided to you is invalid. eg,
246 /// access after you return from the call in which a `!data_is_owned` `Transaction` is provided to
247 /// you would be invalid.
248 ///
249 /// Note that, while it may change in the future, because transactions on the Rust side are stored
250 /// in a deserialized form, all `Transaction`s generated on the Rust side will have `data_is_owned`
251 /// set. Similarly, while it may change in the future, all `Transaction`s you pass to Rust may have
252 /// `data_is_owned` either set or unset at your discretion.
253 pub struct Transaction {
254         /// The serialized transaction data.
255         ///
256         /// This is non-const for your convenience, an object passed to Rust is never written to.
257         pub data: *mut u8,
258         /// The length of the serialized transaction
259         pub datalen: usize,
260         /// Whether the data pointed to by `data` should be freed or not.
261         pub data_is_owned: bool,
262 }
263 impl Transaction {
264         fn from_vec(vec: Vec<u8>) -> Self {
265                 let datalen = vec.len();
266                 let data = Box::into_raw(vec.into_boxed_slice());
267                 Self {
268                         data: unsafe { (*data).as_mut_ptr() },
269                         datalen,
270                         data_is_owned: true,
271                 }
272         }
273         pub(crate) fn into_bitcoin(&self) -> BitcoinTransaction {
274                 if self.datalen == 0 { panic!("0-length buffer can never represent a valid Transaction"); }
275                 ::bitcoin::consensus::encode::deserialize(unsafe { std::slice::from_raw_parts(self.data, self.datalen) }).unwrap()
276         }
277         pub(crate) fn from_bitcoin(btc: &BitcoinTransaction) -> Self {
278                 let vec = ::bitcoin::consensus::encode::serialize(btc);
279                 Self::from_vec(vec)
280         }
281 }
282 impl Drop for Transaction {
283         fn drop(&mut self) {
284                 if self.data_is_owned && self.datalen != 0 {
285                         let _ = derived::CVec_u8Z { data: self.data as *mut u8, datalen: self.datalen };
286                 }
287         }
288 }
289 impl Clone for Transaction {
290         fn clone(&self) -> Self {
291                 let sl = unsafe { std::slice::from_raw_parts(self.data, self.datalen) };
292                 let mut v = Vec::new();
293                 v.extend_from_slice(&sl);
294                 Self::from_vec(v)
295         }
296 }
297 #[no_mangle]
298 /// Frees the data buffer, if data_is_owned is set and datalen > 0.
299 pub extern "C" fn Transaction_free(_res: Transaction) { }
300
301 pub(crate) fn bitcoin_to_C_outpoint(outpoint: ::bitcoin::blockdata::transaction::OutPoint) -> crate::lightning::chain::transaction::OutPoint {
302         crate::lightning::chain::transaction::OutPoint_new(ThirtyTwoBytes { data: outpoint.txid.into_inner() }, outpoint.vout.try_into().unwrap())
303 }
304 pub(crate) fn C_to_bitcoin_outpoint(outpoint: crate::lightning::chain::transaction::OutPoint) -> ::bitcoin::blockdata::transaction::OutPoint {
305         unsafe {
306                 ::bitcoin::blockdata::transaction::OutPoint {
307                         txid: (*outpoint.inner).txid, vout: (*outpoint.inner).index as u32
308                 }
309         }
310 }
311
312 #[repr(C)]
313 #[derive(Clone)]
314 /// A transaction output including a scriptPubKey and value.
315 /// This type *does* own its own memory, so must be free'd appropriately.
316 pub struct TxOut {
317         /// The script_pubkey in this output
318         pub script_pubkey: derived::CVec_u8Z,
319         /// The value, in satoshis, of this output
320         pub value: u64,
321 }
322
323 impl TxOut {
324         pub(crate) fn into_rust(mut self) -> ::bitcoin::blockdata::transaction::TxOut {
325                 ::bitcoin::blockdata::transaction::TxOut {
326                         script_pubkey: self.script_pubkey.into_rust().into(),
327                         value: self.value,
328                 }
329         }
330         pub(crate) fn from_rust(txout: ::bitcoin::blockdata::transaction::TxOut) -> Self {
331                 Self {
332                         script_pubkey: derived::CVec_u8Z::from(txout.script_pubkey.into_bytes()),
333                         value: txout.value
334                 }
335         }
336 }
337
338 #[no_mangle]
339 /// Convenience function for constructing a new TxOut
340 pub extern "C" fn TxOut_new(script_pubkey: derived::CVec_u8Z, value: u64) -> TxOut {
341         TxOut { script_pubkey, value }
342 }
343 #[no_mangle]
344 /// Frees the data pointed to by script_pubkey.
345 pub extern "C" fn TxOut_free(_res: TxOut) { }
346 #[no_mangle]
347 /// Creates a new TxOut which has the same data as `orig` but with a new script buffer.
348 pub extern "C" fn TxOut_clone(orig: &TxOut) -> TxOut { orig.clone() }
349
350 #[repr(C)]
351 /// A "slice" referencing some byte array. This is simply a length-tagged pointer which does not
352 /// own the memory pointed to by data.
353 pub struct u8slice {
354         /// A pointer to the byte buffer
355         pub data: *const u8,
356         /// The number of bytes pointed to by `data`.
357         pub datalen: usize
358 }
359 impl u8slice {
360         pub(crate) fn from_slice(s: &[u8]) -> Self {
361                 Self {
362                         data: s.as_ptr(),
363                         datalen: s.len(),
364                 }
365         }
366         pub(crate) fn to_slice(&self) -> &[u8] {
367                 if self.datalen == 0 { return &[]; }
368                 unsafe { std::slice::from_raw_parts(self.data, self.datalen) }
369         }
370         pub(crate) fn to_reader<'a>(&'a self) -> Cursor<&'a [u8]> {
371                 let sl = self.to_slice();
372                 Cursor::new(sl)
373         }
374         pub(crate) fn from_vec(v: &derived::CVec_u8Z) -> u8slice {
375                 Self::from_slice(v.as_slice())
376         }
377 }
378 pub(crate) fn reader_to_vec<R: Read>(r: &mut R) -> derived::CVec_u8Z {
379         let mut res = Vec::new();
380         r.read_to_end(&mut res).unwrap();
381         derived::CVec_u8Z::from(res)
382 }
383
384 #[repr(C)]
385 #[derive(Copy, Clone)]
386 /// Arbitrary 32 bytes, which could represent one of a few different things. You probably want to
387 /// look up the corresponding function in rust-lightning's docs.
388 pub struct ThirtyTwoBytes {
389         /// The thirty-two bytes
390         pub data: [u8; 32],
391 }
392 impl ThirtyTwoBytes {
393         pub(crate) fn null() -> Self {
394                 Self { data: [0; 32] }
395         }
396 }
397
398 #[repr(C)]
399 /// A 3-byte byte array.
400 pub struct ThreeBytes { /** The three bytes */ pub data: [u8; 3], }
401 #[derive(Clone)]
402 #[repr(C)]
403 /// A 4-byte byte array.
404 pub struct FourBytes { /** The four bytes */ pub data: [u8; 4], }
405 #[derive(Clone)]
406 #[repr(C)]
407 /// A 10-byte byte array.
408 pub struct TenBytes { /** The ten bytes */ pub data: [u8; 10], }
409 #[derive(Clone)]
410 #[repr(C)]
411 /// A 16-byte byte array.
412 pub struct SixteenBytes { /** The sixteen bytes */ pub data: [u8; 16], }
413 #[derive(Clone)]
414 #[repr(C)]
415 /// A 20-byte byte array.
416 pub struct TwentyBytes { /** The twenty bytes */ pub data: [u8; 20], }
417
418 pub(crate) struct VecWriter(pub Vec<u8>);
419 impl lightning::util::ser::Writer for VecWriter {
420         fn write_all(&mut self, buf: &[u8]) -> Result<(), ::std::io::Error> {
421                 self.0.extend_from_slice(buf);
422                 Ok(())
423         }
424 }
425 pub(crate) fn serialize_obj<I: lightning::util::ser::Writeable>(i: &I) -> derived::CVec_u8Z {
426         let mut out = VecWriter(Vec::new());
427         i.write(&mut out).unwrap();
428         derived::CVec_u8Z::from(out.0)
429 }
430 pub(crate) fn deserialize_obj<I: lightning::util::ser::Readable>(s: u8slice) -> Result<I, lightning::ln::msgs::DecodeError> {
431         I::read(&mut s.to_slice())
432 }
433 pub(crate) fn deserialize_obj_arg<A, I: lightning::util::ser::ReadableArgs<A>>(s: u8slice, args: A) -> Result<I, lightning::ln::msgs::DecodeError> {
434         I::read(&mut s.to_slice(), args)
435 }
436
437 #[repr(C)]
438 #[derive(Clone)]
439 /// A Rust str object, ie a reference to a UTF8-valid string.
440 /// This is *not* null-terminated so cannot be used directly as a C string!
441 pub struct Str {
442         /// A pointer to the string's bytes, in UTF8 encoding
443         pub chars: *const u8,
444         /// The number of bytes (not characters!) pointed to by `chars`
445         pub len: usize,
446         /// Whether the data pointed to by `chars` should be freed or not.
447         pub chars_is_owned: bool,
448 }
449 impl Into<Str> for &'static str {
450         fn into(self) -> Str {
451                 Str { chars: self.as_ptr(), len: self.len(), chars_is_owned: false }
452         }
453 }
454 impl Str {
455         pub(crate) fn into_str(&self) -> &'static str {
456                 if self.len == 0 { return ""; }
457                 std::str::from_utf8(unsafe { std::slice::from_raw_parts(self.chars, self.len) }).unwrap()
458         }
459         pub(crate) fn into_string(mut self) -> String {
460                 let bytes = if self.len == 0 {
461                         Vec::new()
462                 } else if self.chars_is_owned {
463                         let ret = unsafe {
464                                 Box::from_raw(std::slice::from_raw_parts_mut(unsafe { self.chars as *mut u8 }, self.len))
465                         }.into();
466                         self.chars_is_owned = false;
467                         ret
468                 } else {
469                         let mut ret = Vec::with_capacity(self.len);
470                         ret.extend_from_slice(unsafe { std::slice::from_raw_parts(self.chars, self.len) });
471                         ret
472                 };
473                 String::from_utf8(bytes).unwrap()
474         }
475 }
476 impl Into<Str> for String {
477         fn into(self) -> Str {
478                 let s = Box::leak(self.into_boxed_str());
479                 Str { chars: s.as_ptr(), len: s.len(), chars_is_owned: true }
480         }
481 }
482
483 impl Drop for Str {
484         fn drop(&mut self) {
485                 if self.chars_is_owned && self.len != 0 {
486                         let _ = derived::CVec_u8Z { data: self.chars as *mut u8, datalen: self.len };
487                 }
488         }
489 }
490 #[no_mangle]
491 /// Frees the data buffer, if chars_is_owned is set and len > 0.
492 pub extern "C" fn Str_free(_res: Str) { }
493
494 // Note that the C++ headers memset(0) all the Templ types to avoid deallocation!
495 // Thus, they must gracefully handle being completely null in _free.
496
497 // TODO: Integer/bool primitives should avoid the pointer indirection for underlying types
498 // everywhere in the containers.
499
500 #[repr(C)]
501 pub(crate) union CResultPtr<O, E> {
502         pub(crate) result: *mut O,
503         pub(crate) err: *mut E,
504 }
505 #[repr(C)]
506 pub(crate) struct CResultTempl<O, E> {
507         pub(crate) contents: CResultPtr<O, E>,
508         pub(crate) result_ok: bool,
509 }
510 impl<O, E> CResultTempl<O, E> {
511         pub(crate) extern "C" fn ok(o: O) -> Self {
512                 CResultTempl {
513                         contents: CResultPtr {
514                                 result: Box::into_raw(Box::new(o)),
515                         },
516                         result_ok: true,
517                 }
518         }
519         pub(crate) extern "C" fn err(e: E) -> Self {
520                 CResultTempl {
521                         contents: CResultPtr {
522                                 err: Box::into_raw(Box::new(e)),
523                         },
524                         result_ok: false,
525                 }
526         }
527 }
528 impl<O, E> Drop for CResultTempl<O, E> {
529         fn drop(&mut self) {
530                 if self.result_ok {
531                         if unsafe { !self.contents.result.is_null() } {
532                                 unsafe { Box::from_raw(self.contents.result) };
533                         }
534                 } else if unsafe { !self.contents.err.is_null() } {
535                         unsafe { Box::from_raw(self.contents.err) };
536                 }
537         }
538 }
539
540 /// Utility to make it easy to set a pointer to null and get its original value in line.
541 pub(crate) trait TakePointer<T> {
542         fn take_ptr(&mut self) -> T;
543 }
544 impl<T> TakePointer<*const T> for *const T {
545         fn take_ptr(&mut self) -> *const T {
546                 let ret = *self;
547                 *self = std::ptr::null();
548                 ret
549         }
550 }
551 impl<T> TakePointer<*mut T> for *mut T {
552         fn take_ptr(&mut self) -> *mut T {
553                 let ret = *self;
554                 *self = std::ptr::null_mut();
555                 ret
556         }
557 }
558
559
560 pub(crate) mod ObjOps {
561         #[inline]
562         #[must_use = "returns new dangling pointer"]
563         pub(crate) fn heap_alloc<T>(obj: T) -> *mut T {
564                 let ptr = Box::into_raw(Box::new(obj));
565                 nonnull_ptr_to_inner(ptr)
566         }
567         #[inline]
568         pub(crate) fn nonnull_ptr_to_inner<T>(ptr: *const T) -> *mut T {
569                 if core::mem::size_of::<T>() == 0 {
570                         // We map `None::<T>` as `T { inner: null, .. }` which works great for all
571                         // non-Zero-Sized-Types `T`.
572                         // For ZSTs, we need to differentiate between null implying `None` and null implying
573                         // `Some` with no allocation.
574                         // Thus, for ZSTs, we add one (usually) page here, which should always be aligned.
575                         // Note that this relies on undefined behavior! A pointer to NULL may be valid, but a
576                         // pointer to NULL + 4096 is almost certainly not. That said, Rust's existing use of
577                         // `(*mut T)1` for the pointer we're adding to is also not defined, so we should be
578                         // fine.
579                         // Note that we add 4095 here as at least the Java client assumes that the low bit on
580                         // any heap pointer is 0, which is generally provided by malloc, but which is not true
581                         // for ZSTs "allocated" by `Box::new`.
582                         debug_assert_eq!(ptr as usize, 1);
583                         unsafe { (ptr as *mut T).cast::<u8>().add(4096 - 1).cast::<T>() }
584                 } else {
585                         // In order to get better test coverage, also increment non-ZST pointers with
586                         // --cfg=test_mod_pointers, which is set in genbindings.sh for debug builds.
587                         #[cfg(test_mod_pointers)]
588                         unsafe { (ptr as *mut T).cast::<u8>().add(4096).cast::<T>() }
589                         #[cfg(not(test_mod_pointers))]
590                         unsafe { ptr as *mut T }
591                 }
592         }
593         #[inline]
594         /// Invert nonnull_ptr_to_inner
595         pub(crate) fn untweak_ptr<T>(ptr: *mut T) -> *mut T {
596                 if core::mem::size_of::<T>() == 0 {
597                         unsafe { ptr.cast::<u8>().sub(4096 - 1).cast::<T>() }
598                 } else {
599                         #[cfg(test_mod_pointers)]
600                         unsafe { ptr.cast::<u8>().sub(4096).cast::<T>() }
601                         #[cfg(not(test_mod_pointers))]
602                         ptr
603                 }
604         }
605 }