linux flutter example with bridge to rust and build system

This commit is contained in:
John Smith 2022-01-29 13:23:10 -05:00
parent cbffc381c1
commit 0c6aa6d439
14 changed files with 370 additions and 71 deletions

View File

@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:veilid/veilid.dart'; import 'package:veilid/veilid.dart';
@ -16,7 +16,7 @@ class MyApp extends StatefulWidget {
} }
class _MyAppState extends State<MyApp> { class _MyAppState extends State<MyApp> {
String _platformVersion = 'Unknown'; String _veilidVersion = 'Unknown';
@override @override
void initState() { void initState() {
@ -26,14 +26,13 @@ class _MyAppState extends State<MyApp> {
// Platform messages are asynchronous, so we initialize in an async method. // Platform messages are asynchronous, so we initialize in an async method.
Future<void> initPlatformState() async { Future<void> initPlatformState() async {
String platformVersion; String veilidVersion;
// Platform messages may fail, so we use a try/catch PlatformException. // Platform messages may fail, so we use a try/catch PlatformException.
// We also handle the message potentially returning null. // We also handle the message potentially returning null.
try { try {
platformVersion = veilidVersion = await Veilid.api.veilidVersionString();
await Veilid.platformVersion ?? 'Unknown platform version';
} on PlatformException { } on PlatformException {
platformVersion = 'Failed to get platform version.'; veilidVersion = 'Failed to get veilid version.';
} }
// If the widget was removed from the tree while the asynchronous platform // If the widget was removed from the tree while the asynchronous platform
@ -42,7 +41,7 @@ class _MyAppState extends State<MyApp> {
if (!mounted) return; if (!mounted) return;
setState(() { setState(() {
_platformVersion = platformVersion; _veilidVersion = veilidVersion;
}); });
} }
@ -51,10 +50,10 @@ class _MyAppState extends State<MyApp> {
return MaterialApp( return MaterialApp(
home: Scaffold( home: Scaffold(
appBar: AppBar( appBar: AppBar(
title: const Text('Plugin example app'), title: const Text('Veilid Plugin Example App'),
), ),
body: Center( body: Center(
child: Text('Running on: $_platformVersion\n'), child: Text('Veilid version: $_veilidVersion\n'),
), ),
), ),
); );

View File

@ -0,0 +1,2 @@
#import "GeneratedPluginRegistrant.h"
#import "bridge_generated.h"

View File

@ -3,12 +3,12 @@ import UIKit
public class SwiftVeilidPlugin: NSObject, FlutterPlugin { public class SwiftVeilidPlugin: NSObject, FlutterPlugin {
public static func register(with registrar: FlutterPluginRegistrar) { public static func register(with registrar: FlutterPluginRegistrar) {
let channel = FlutterMethodChannel(name: "veilid", binaryMessenger: registrar.messenger()) // No channel, FFI plugin
let instance = SwiftVeilidPlugin() print("dummy_value=\(dummy_method_to_enforce_bundling())");
registrar.addMethodCallDelegate(instance, channel: channel)
} }
public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
result("iOS " + UIDevice.current.systemVersion) // Noop
result(nil)
} }
} }

View File

@ -14,7 +14,7 @@ typedef struct wire_StringList {
typedef struct wire_VeilidConfig { typedef struct wire_VeilidConfig {
struct wire_uint_8_list *program_name; struct wire_uint_8_list *program_name;
struct wire_uint_8_list *namespace_; struct wire_uint_8_list *veilid_namespace;
bool capabilities__protocol_udp; bool capabilities__protocol_udp;
bool capabilities__protocol_connect_tcp; bool capabilities__protocol_connect_tcp;
bool capabilities__protocol_accept_tcp; bool capabilities__protocol_accept_tcp;

View File

@ -40,7 +40,7 @@ enum AttachmentState {
class VeilidConfig { class VeilidConfig {
final String programName; final String programName;
final String namespace; final String veilidNamespace;
final bool capabilitiesProtocolUdp; final bool capabilitiesProtocolUdp;
final bool capabilitiesProtocolConnectTcp; final bool capabilitiesProtocolConnectTcp;
final bool capabilitiesProtocolAcceptTcp; final bool capabilitiesProtocolAcceptTcp;
@ -108,7 +108,7 @@ class VeilidConfig {
VeilidConfig({ VeilidConfig({
required this.programName, required this.programName,
required this.namespace, required this.veilidNamespace,
required this.capabilitiesProtocolUdp, required this.capabilitiesProtocolUdp,
required this.capabilitiesProtocolConnectTcp, required this.capabilitiesProtocolConnectTcp,
required this.capabilitiesProtocolAcceptTcp, required this.capabilitiesProtocolAcceptTcp,
@ -332,7 +332,7 @@ class VeilidFlutterImpl extends FlutterRustBridgeBase<VeilidFlutterWire>
void _api_fill_to_wire_veilid_config( void _api_fill_to_wire_veilid_config(
VeilidConfig apiObj, wire_VeilidConfig wireObj) { VeilidConfig apiObj, wire_VeilidConfig wireObj) {
wireObj.program_name = _api2wire_String(apiObj.programName); wireObj.program_name = _api2wire_String(apiObj.programName);
wireObj.namespace = _api2wire_String(apiObj.namespace); wireObj.veilid_namespace = _api2wire_String(apiObj.veilidNamespace);
wireObj.capabilities__protocol_udp = wireObj.capabilities__protocol_udp =
_api2wire_bool(apiObj.capabilitiesProtocolUdp); _api2wire_bool(apiObj.capabilitiesProtocolUdp);
wireObj.capabilities__protocol_connect_tcp = wireObj.capabilities__protocol_connect_tcp =
@ -708,7 +708,7 @@ class wire_StringList extends ffi.Struct {
class wire_VeilidConfig extends ffi.Struct { class wire_VeilidConfig extends ffi.Struct {
external ffi.Pointer<wire_uint_8_list> program_name; external ffi.Pointer<wire_uint_8_list> program_name;
external ffi.Pointer<wire_uint_8_list> namespace_; external ffi.Pointer<wire_uint_8_list> veilid_namespace;
@ffi.Uint8() @ffi.Uint8()
external int capabilities__protocol_udp; external int capabilities__protocol_udp;

View File

@ -0,0 +1,230 @@
// coverage:ignore-file
// GENERATED CODE - DO NOT MODIFY BY HAND
// ignore_for_file: type=lint
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target
part of 'bridge_generated.dart';
// **************************************************************************
// FreezedGenerator
// **************************************************************************
T _$identity<T>(T value) => value;
final _privateConstructorUsedError = UnsupportedError(
'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more informations: https://github.com/rrousselGit/freezed#custom-getters-and-methods');
/// @nodoc
class _$VeilidUpdateTearOff {
const _$VeilidUpdateTearOff();
Attachment attachment(AttachmentState field0) {
return Attachment(
field0,
);
}
}
/// @nodoc
const $VeilidUpdate = _$VeilidUpdateTearOff();
/// @nodoc
mixin _$VeilidUpdate {
AttachmentState get field0 => throw _privateConstructorUsedError;
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(AttachmentState field0) attachment,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function(AttachmentState field0)? attachment,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(AttachmentState field0)? attachment,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Attachment value) attachment,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(Attachment value)? attachment,
}) =>
throw _privateConstructorUsedError;
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Attachment value)? attachment,
required TResult orElse(),
}) =>
throw _privateConstructorUsedError;
@JsonKey(ignore: true)
$VeilidUpdateCopyWith<VeilidUpdate> get copyWith =>
throw _privateConstructorUsedError;
}
/// @nodoc
abstract class $VeilidUpdateCopyWith<$Res> {
factory $VeilidUpdateCopyWith(
VeilidUpdate value, $Res Function(VeilidUpdate) then) =
_$VeilidUpdateCopyWithImpl<$Res>;
$Res call({AttachmentState field0});
}
/// @nodoc
class _$VeilidUpdateCopyWithImpl<$Res> implements $VeilidUpdateCopyWith<$Res> {
_$VeilidUpdateCopyWithImpl(this._value, this._then);
final VeilidUpdate _value;
// ignore: unused_field
final $Res Function(VeilidUpdate) _then;
@override
$Res call({
Object? field0 = freezed,
}) {
return _then(_value.copyWith(
field0: field0 == freezed
? _value.field0
: field0 // ignore: cast_nullable_to_non_nullable
as AttachmentState,
));
}
}
/// @nodoc
abstract class $AttachmentCopyWith<$Res>
implements $VeilidUpdateCopyWith<$Res> {
factory $AttachmentCopyWith(
Attachment value, $Res Function(Attachment) then) =
_$AttachmentCopyWithImpl<$Res>;
@override
$Res call({AttachmentState field0});
}
/// @nodoc
class _$AttachmentCopyWithImpl<$Res> extends _$VeilidUpdateCopyWithImpl<$Res>
implements $AttachmentCopyWith<$Res> {
_$AttachmentCopyWithImpl(Attachment _value, $Res Function(Attachment) _then)
: super(_value, (v) => _then(v as Attachment));
@override
Attachment get _value => super._value as Attachment;
@override
$Res call({
Object? field0 = freezed,
}) {
return _then(Attachment(
field0 == freezed
? _value.field0
: field0 // ignore: cast_nullable_to_non_nullable
as AttachmentState,
));
}
}
/// @nodoc
class _$Attachment implements Attachment {
const _$Attachment(this.field0);
@override
final AttachmentState field0;
@override
String toString() {
return 'VeilidUpdate.attachment(field0: $field0)';
}
@override
bool operator ==(dynamic other) {
return identical(this, other) ||
(other.runtimeType == runtimeType &&
other is Attachment &&
const DeepCollectionEquality().equals(other.field0, field0));
}
@override
int get hashCode =>
Object.hash(runtimeType, const DeepCollectionEquality().hash(field0));
@JsonKey(ignore: true)
@override
$AttachmentCopyWith<Attachment> get copyWith =>
_$AttachmentCopyWithImpl<Attachment>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function(AttachmentState field0) attachment,
}) {
return attachment(field0);
}
@override
@optionalTypeArgs
TResult? whenOrNull<TResult extends Object?>({
TResult Function(AttachmentState field0)? attachment,
}) {
return attachment?.call(field0);
}
@override
@optionalTypeArgs
TResult maybeWhen<TResult extends Object?>({
TResult Function(AttachmentState field0)? attachment,
required TResult orElse(),
}) {
if (attachment != null) {
return attachment(field0);
}
return orElse();
}
@override
@optionalTypeArgs
TResult map<TResult extends Object?>({
required TResult Function(Attachment value) attachment,
}) {
return attachment(this);
}
@override
@optionalTypeArgs
TResult? mapOrNull<TResult extends Object?>({
TResult Function(Attachment value)? attachment,
}) {
return attachment?.call(this);
}
@override
@optionalTypeArgs
TResult maybeMap<TResult extends Object?>({
TResult Function(Attachment value)? attachment,
required TResult orElse(),
}) {
if (attachment != null) {
return attachment(this);
}
return orElse();
}
}
abstract class Attachment implements VeilidUpdate {
const factory Attachment(AttachmentState field0) = _$Attachment;
@override
AttachmentState get field0;
@override
@JsonKey(ignore: true)
$AttachmentCopyWith<Attachment> get copyWith =>
throw _privateConstructorUsedError;
}

View File

@ -1,13 +1,38 @@
import 'dart:async'; import 'dart:async';
import 'dart:ffi';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter/material.dart';
import 'package:veilid/bridge_generated.dart'; import 'package:veilid/bridge_generated.dart';
class Veilid { const base = 'veilid_flutter';
static const MethodChannel _channel = MethodChannel('veilid'); final path = Platform.isWindows
? '$base.dll'
: Platform.isMacOS
? 'lib$base.dylib'
: 'lib$base.so';
late final dylib = Platform.isIOS ? DynamicLibrary.process() : DynamicLibrary.open(path);
late final veilidApi = VeilidFlutterImpl(dylib);
static Future<String?> get platformVersion async { class Veilid {
final String? version = await _channel.invokeMethod('getPlatformVersion');
return version; static VeilidFlutterImpl get api {
if (veilidApi == null) {
throw PlatformException(
code: 'Library missing',
details: 'veilid_core library could not be loaded dynamically',
);
} }
return veilidApi;
}
// static const MethodChannel _channel = MethodChannel('veilid');
// static Future<String?> get platformVersion async {
// final String? version = await _channel.invokeMethod('getPlatformVersion');
// return version;
// }
} }

View File

@ -8,37 +8,34 @@ import 'dart:html' as html show window;
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_web_plugins/flutter_web_plugins.dart'; import 'package:flutter_web_plugins/flutter_web_plugins.dart';
// xxx link in WASM version of veilid-flutter
/// A web implementation of the Veilid plugin. /// A web implementation of the Veilid plugin.
class VeilidWeb { class VeilidWeb {
static void registerWith(Registrar registrar) { static void registerWith(Registrar registrar) {
final MethodChannel channel = MethodChannel( // final MethodChannel channel = MethodChannel(
'veilid', // 'veilid',
const StandardMethodCodec(), // const StandardMethodCodec(),
registrar, // registrar,
); // );
final pluginInstance = VeilidWeb(); // final pluginInstance = VeilidWeb();
channel.setMethodCallHandler(pluginInstance.handleMethodCall); // channel.setMethodCallHandler(pluginInstance.handleMethodCall);
} }
/// Handles method calls over the MethodChannel of this plugin. /// Handles method calls over the MethodChannel of this plugin.
/// Note: Check the "federated" architecture for a new way of doing this: /// Note: Check the "federated" architecture for a new way of doing this:
/// https://flutter.dev/go/federated-plugins /// https://flutter.dev/go/federated-plugins
Future<dynamic> handleMethodCall(MethodCall call) async { Future<dynamic> handleMethodCall(MethodCall call) async {
switch (call.method) { // switch (call.method) {
case 'getPlatformVersion': // case 'getPlatformVersion':
return getPlatformVersion(); // return getPlatformVersion();
default: // default:
throw PlatformException( throw PlatformException(
code: 'Unimplemented', code: 'Unimplemented',
details: 'veilid for web doesn\'t implement \'${call.method}\'', details: 'veilid for web doesn\'t implement \'${call.method}\'',
); );
} // }
} }
/// Returns a [String] containing the version of the platform.
Future<String> getPlatformVersion() {
final version = html.window.navigator.userAgent;
return Future.value(version);
}
} }

View File

@ -18,8 +18,9 @@ target_include_directories(${PLUGIN_NAME} INTERFACE
target_link_libraries(${PLUGIN_NAME} PRIVATE flutter) target_link_libraries(${PLUGIN_NAME} PRIVATE flutter)
target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK) target_link_libraries(${PLUGIN_NAME} PRIVATE PkgConfig::GTK)
include(./rust.cmake)
# List of absolute paths to libraries that should be bundled with the plugin # List of absolute paths to libraries that should be bundled with the plugin
set(veilid_bundled_libraries set(veilid_bundled_libraries
"" "$<TARGET_FILE:${CRATE_NAME}-shared>"
PARENT_SCOPE PARENT_SCOPE
) )

View File

@ -0,0 +1,23 @@
# We include Corrosion inline here, but ideally in a project with
# many dependencies we would need to install Corrosion on the system.
# See instructions on https://github.com/AndrewGaspar/corrosion#cmake-install
# Once done, uncomment this line:
# find_package(Corrosion REQUIRED)
include(FetchContent)
FetchContent_Declare(
Corrosion
GIT_REPOSITORY https://github.com/AndrewGaspar/corrosion.git
GIT_TAG origin/master # Optionally specify a version tag or branch here
)
FetchContent_MakeAvailable(Corrosion)
corrosion_import_crate(MANIFEST_PATH ${CMAKE_SOURCE_DIR}/../../rust/Cargo.toml)
# Flutter-specific
set(CRATE_NAME "veilid-flutter")
target_link_libraries(${PLUGIN_NAME} PUBLIC ${CRATE_NAME})
# list(APPEND PLUGIN_BUNDLED_LIBRARIES $<TARGET_FILE:${CRATE_NAME}-shared>)

View File

@ -10,7 +10,8 @@
(G_TYPE_CHECK_INSTANCE_CAST((obj), veilid_plugin_get_type(), \ (G_TYPE_CHECK_INSTANCE_CAST((obj), veilid_plugin_get_type(), \
VeilidPlugin)) VeilidPlugin))
struct _VeilidPlugin { struct _VeilidPlugin
{
GObject parent_instance; GObject parent_instance;
}; };
@ -19,41 +20,46 @@ G_DEFINE_TYPE(VeilidPlugin, veilid_plugin, g_object_get_type())
// Called when a method call is received from Flutter. // Called when a method call is received from Flutter.
static void veilid_plugin_handle_method_call( static void veilid_plugin_handle_method_call(
VeilidPlugin *self, VeilidPlugin *self,
FlMethodCall* method_call) { FlMethodCall *method_call)
{
g_autoptr(FlMethodResponse) response = nullptr; g_autoptr(FlMethodResponse) response = nullptr;
const gchar* method = fl_method_call_get_name(method_call); //const gchar *method = fl_method_call_get_name(method_call);
if (strcmp(method, "getPlatformVersion") == 0) { // if (strcmp(method, "getPlatformVersion") == 0) {
struct utsname uname_data = {}; // struct utsname uname_data = {};
uname(&uname_data); // uname(&uname_data);
g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version); // g_autofree gchar *version = g_strdup_printf("Linux %s", uname_data.version);
g_autoptr(FlValue) result = fl_value_new_string(version); // g_autoptr(FlValue) result = fl_value_new_string(version);
response = FL_METHOD_RESPONSE(fl_method_success_response_new(result)); // response = FL_METHOD_RESPONSE(fl_method_success_response_new(result));
} else { // } else {
response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new()); response = FL_METHOD_RESPONSE(fl_method_not_implemented_response_new());
} // }
fl_method_call_respond(method_call, response, nullptr); fl_method_call_respond(method_call, response, nullptr);
} }
static void veilid_plugin_dispose(GObject* object) { static void veilid_plugin_dispose(GObject *object)
{
G_OBJECT_CLASS(veilid_plugin_parent_class)->dispose(object); G_OBJECT_CLASS(veilid_plugin_parent_class)->dispose(object);
} }
static void veilid_plugin_class_init(VeilidPluginClass* klass) { static void veilid_plugin_class_init(VeilidPluginClass *klass)
{
G_OBJECT_CLASS(klass)->dispose = veilid_plugin_dispose; G_OBJECT_CLASS(klass)->dispose = veilid_plugin_dispose;
} }
static void veilid_plugin_init(VeilidPlugin *self) {} static void veilid_plugin_init(VeilidPlugin *self) {}
static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call, static void method_call_cb(FlMethodChannel *channel, FlMethodCall *method_call,
gpointer user_data) { gpointer user_data)
{
VeilidPlugin *plugin = VEILID_PLUGIN(user_data); VeilidPlugin *plugin = VEILID_PLUGIN(user_data);
veilid_plugin_handle_method_call(plugin, method_call); veilid_plugin_handle_method_call(plugin, method_call);
} }
void veilid_plugin_register_with_registrar(FlPluginRegistrar* registrar) { void veilid_plugin_register_with_registrar(FlPluginRegistrar *registrar)
{
VeilidPlugin *plugin = VEILID_PLUGIN( VeilidPlugin *plugin = VEILID_PLUGIN(
g_object_new(veilid_plugin_get_type(), nullptr)); g_object_new(veilid_plugin_get_type(), nullptr));

View File

@ -94,5 +94,21 @@ fn main() {
.wait() .wait()
.expect("flutter_rust_bridge_codegen was not running"); .expect("flutter_rust_bridge_codegen was not running");
//println!("cargo:rerun-if-changed={}", input_path.to_str().unwrap()); // Build freezed
// Run: flutter pub run build_runner build
let mut command = Command::new("flutter");
command.args([
OsStr::new("pub"),
OsStr::new("run"),
OsStr::new("build_runner"),
OsStr::new("build"),
]);
let mut child = command
.spawn()
.expect("'flutter pub run build_runner build' did not execute correctly");
child
.wait()
.expect("'flutter pub run build_runner build' was not running");
} }

View File

@ -42,7 +42,7 @@ async fn take_veilid_api() -> Result<veilid_core::VeilidAPI> {
#[allow(non_snake_case)] #[allow(non_snake_case)]
pub struct VeilidConfig { pub struct VeilidConfig {
pub program_name: String, pub program_name: String,
pub namespace: String, pub veilid_namespace: String,
// Capabilities // Capabilities
pub capabilities__protocol_udp: bool, pub capabilities__protocol_udp: bool,
pub capabilities__protocol_connect_tcp: bool, pub capabilities__protocol_connect_tcp: bool,
@ -126,7 +126,7 @@ impl VeilidConfig {
pub fn get_by_str(&self, key: &str) -> std::result::Result<Box<dyn std::any::Any + Send + 'static>, String> { pub fn get_by_str(&self, key: &str) -> std::result::Result<Box<dyn std::any::Any + Send + 'static>, String> {
let out: Box<dyn core::any::Any + Send> = match key { let out: Box<dyn core::any::Any + Send> = match key {
"program_name" => Box::new(self.program_name.clone()), "program_name" => Box::new(self.program_name.clone()),
"namespace" => Box::new(self.namespace.clone()), "namespace" => Box::new(self.veilid_namespace.clone()),
"capabilities.protocol_udp" => Box::new(self.capabilities__protocol_udp.clone()), "capabilities.protocol_udp" => Box::new(self.capabilities__protocol_udp.clone()),
"capabilities.protocol_connect_tcp" => Box::new(self.capabilities__protocol_connect_tcp.clone()), "capabilities.protocol_connect_tcp" => Box::new(self.capabilities__protocol_connect_tcp.clone()),
"capabilities.protocol_accept_tcp" => Box::new(self.capabilities__protocol_accept_tcp.clone()), "capabilities.protocol_accept_tcp" => Box::new(self.capabilities__protocol_accept_tcp.clone()),

View File

@ -96,7 +96,7 @@ pub struct wire_uint_8_list {
#[derive(Clone)] #[derive(Clone)]
pub struct wire_VeilidConfig { pub struct wire_VeilidConfig {
program_name: *mut wire_uint_8_list, program_name: *mut wire_uint_8_list,
namespace: *mut wire_uint_8_list, veilid_namespace: *mut wire_uint_8_list,
capabilities__protocol_udp: bool, capabilities__protocol_udp: bool,
capabilities__protocol_connect_tcp: bool, capabilities__protocol_connect_tcp: bool,
capabilities__protocol_accept_tcp: bool, capabilities__protocol_accept_tcp: bool,
@ -275,7 +275,7 @@ impl Wire2Api<VeilidConfig> for wire_VeilidConfig {
fn wire2api(self) -> VeilidConfig { fn wire2api(self) -> VeilidConfig {
VeilidConfig { VeilidConfig {
program_name: self.program_name.wire2api(), program_name: self.program_name.wire2api(),
namespace: self.namespace.wire2api(), veilid_namespace: self.veilid_namespace.wire2api(),
capabilities__protocol_udp: self.capabilities__protocol_udp.wire2api(), capabilities__protocol_udp: self.capabilities__protocol_udp.wire2api(),
capabilities__protocol_connect_tcp: self.capabilities__protocol_connect_tcp.wire2api(), capabilities__protocol_connect_tcp: self.capabilities__protocol_connect_tcp.wire2api(),
capabilities__protocol_accept_tcp: self.capabilities__protocol_accept_tcp.wire2api(), capabilities__protocol_accept_tcp: self.capabilities__protocol_accept_tcp.wire2api(),
@ -404,7 +404,7 @@ impl NewWithNullPtr for wire_VeilidConfig {
fn new_with_null_ptr() -> Self { fn new_with_null_ptr() -> Self {
Self { Self {
program_name: core::ptr::null_mut(), program_name: core::ptr::null_mut(),
namespace: core::ptr::null_mut(), veilid_namespace: core::ptr::null_mut(),
capabilities__protocol_udp: Default::default(), capabilities__protocol_udp: Default::default(),
capabilities__protocol_connect_tcp: Default::default(), capabilities__protocol_connect_tcp: Default::default(),
capabilities__protocol_accept_tcp: Default::default(), capabilities__protocol_accept_tcp: Default::default(),