Created
December 29, 2021 07:15
-
-
Save martinmroz/5905c65e129d22a1b56d84f08b35a0f4 to your computer and use it in GitHub Desktop.
Rust -> NSString -> String Bridge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
* Copyright (C) 2019 Martin Mroz | |
* | |
* This software may be modified and distributed under the terms | |
* of the MIT license. See the LICENSE file for details. | |
*/ | |
#import <Foundation/Foundation.h> | |
NS_ASSUME_NONNULL_BEGIN | |
@interface NSString (Bcbp) | |
/** | |
Creates an NSString wrapping the `Bcbp` owned and managed C string. | |
Ownership of the pointer is transferred to the new instance of the receiver. | |
No data is copied, and the contents is deallocated using the appropriate | |
FFI method once no longer required. | |
@return A new instance of the receiver taking ownership of the input, or nil if the input is nil. | |
*/ | |
+ (_Nullable instancetype)IB_stringWithBcbpManagedCStringNoCopy:(char * _Nullable)bcbpCString; | |
/** | |
Creates an NSString wrapping the `Bcbp` owned and managed C string. | |
Ownership of the pointer is transferred to the new instance of the receiver. | |
No data is copied, and the contents is deallocated using the appropriate | |
FFI method once no longer required. | |
@param length The pre-determined length of the `bcbpCString` in bytes. | |
@return A new instance of the receiver taking ownership of the input, or nil if the input is nil. | |
*/ | |
+ (_Nullable instancetype)IB_stringWithBcbpManagedCStringNoCopy:(char * _Nullable)bcbpCString length:(NSUInteger)length; | |
@end | |
NS_ASSUME_NONNULL_END | |
/* | |
* Copyright (C) 2019 Martin Mroz | |
* | |
* This software may be modified and distributed under the terms | |
* of the MIT license. See the LICENSE file for details. | |
*/ | |
#include "iata_bcbp_ffi.h" | |
#import "NSString+Bcbp.h" | |
// Deallocates a string allocated by the Bcbp FFI library. | |
static void BcbpCStringDeallocatorDeallocate(void *ptr, void *info) | |
{ | |
BcbpDestroyString((char *)ptr); | |
} | |
// Not valid for allocation, a CFAllocatorRef build from this context | |
// is used to defer destruction of strings managed by the Bcbp FFI library. | |
// As a Rust library may not use the system allocator, all pointers returned from | |
// the FFI library must be destroyed therewith. To reduce allocations and avoid | |
// copying all strings into memory managed by the system allocator, | |
// the memory is used directly and destruction is deferred back to the library. | |
static CFAllocatorContext BcbpCStringDeallocatorContext = { | |
.version = 0, | |
.info = NULL, | |
.retain = NULL, | |
.release = NULL, | |
.copyDescription = NULL, | |
.allocate = NULL, | |
.reallocate = NULL, | |
.deallocate = BcbpCStringDeallocatorDeallocate, | |
.preferredSize = NULL, | |
}; | |
@implementation NSString (Bcbp) | |
+ (instancetype)IB_stringWithBcbpManagedCStringNoCopy:(char *)bcbpCString; | |
{ | |
return [self IB_stringWithBcbpManagedCStringNoCopy:bcbpCString length:strlen(bcbpCString)]; | |
} | |
+ (instancetype)IB_stringWithBcbpManagedCStringNoCopy:(char *)bcbpCString length:(NSUInteger)length; | |
{ | |
if (bcbpCString == NULL) { | |
return nil; | |
} | |
static CFAllocatorRef bcbpCStringDeallocator = NULL; | |
static dispatch_once_t onceToken; | |
dispatch_once(&onceToken, ^{ | |
bcbpCStringDeallocator = CFAllocatorCreate(kCFAllocatorDefault, &BcbpCStringDeallocatorContext); | |
}); | |
CFStringRef const managedString = CFStringCreateWithBytesNoCopy( | |
kCFAllocatorDefault, | |
(const UInt8 *)bcbpCString, | |
length, | |
kCFStringEncodingUTF8, | |
false, | |
bcbpCStringDeallocator | |
); | |
return CFBridgingRelease(managedString); | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment