diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..8d94b88
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/gen
diff --git a/Makefile b/Makefile
index 111f2a5..438fc5f 100644
--- a/Makefile
+++ b/Makefile
@@ -6,6 +6,11 @@
 endif
 
 ifdef ANDROID
+	# TODO(nlacasse): Once mojo issue #349 is fixed, start using the
+	# --map-origin flag and refernce .mojo files by an http:// url and not
+	# file:// url, since the latter will never work on android.
+	$(error Android compilation is currently not supported.  Blocked by https://github.com/domokit/mojo/issues/349)
+
 	# Configure compiler and linker for Android.
 	GO_BIN=$(MOJO_DIR)/src/third_party/go/tool/android_arm/bin/go
 	GO_FLAGS=-ldflags=-shared
@@ -28,9 +33,6 @@
 # MOGO_BIN).
 #
 # MOJO_GOPATH must be exported so it can be picked up by MOGO_BIN.
-#
-# TODO(nlacasse): Add make task to build syncbase service using this MOGO_BUILD
-# function.
 export MOJO_GOPATH=$(V23_GOPATH):$(PWD)/gen/go:$(PWD)/go:$(MOJO_BUILD_DIR)/gen/go
 MOGO_BIN=$(MOJO_DIR)/src/mojo/go/go.py
 define MOGO_BUILD
@@ -66,9 +68,12 @@
 	mkdir -p $(dir $@)
 	ar rcs $@ $(MOJO_BUILD_DIR)/obj/mojo/public/platform/native/system.system_thunks.o
 
-gen: gen/dart-pkg/mojom/lib/mojo/examples/echo.mojom.dart gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart gen/go/src/mojom/echo/echo.mojom.go gen/go/src/mojom/syncbase/syncbase.mojom.go
+# TODO(nlacasse): The echo_client and echo_server are currently used to test
+# compilation and mojom binding generation.  We should remove them once they
+# are no longer needed.
+gen: gen/mojo gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart gen/go/src/mojom/syncbase/syncbase.mojom.go gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart gen/go/src/mojom/echo/echo.mojom.go
 
-gen/dart-pkg/mojom/lib/mojo/examples/echo.mojom.dart: mojom/echo.mojom
+gen/dart-pkg/mojom/lib/mojo/echo.mojom.dart: mojom/echo.mojom
 	$(call MOJOM_GEN,$<,gen,dart)
 
 gen/dart-pkg/mojom/lib/mojo/syncbase.mojom.dart: mojom/syncbase.mojom
@@ -82,6 +87,18 @@
 	$(call MOJOM_GEN,$<,gen,go)
 	gofmt -w $@
 
+gen/mojo: gen/mojo/echo_client.mojo gen/mojo/echo_server.mojo
+
+gen/mojo/echo_client.mojo: go/src/echo_client.go $(MOJO_SHARED_LIB)
+	$(call MOGO_BUILD,$<,$@)
+
+gen/mojo/echo_server.mojo: go/src/echo_server.go $(MOJO_SHARED_LIB)
+	$(call MOGO_BUILD,$<,$@)
+
+.PHONY: run-echo-app
+run-echo-app: gen
+	$(MOJO_DIR)/src/mojo/devtools/common/mojo_run $(MOJO_FLAGS) -v --enable-multiprocess $(PWD)/gen/mojo/echo_client.mojo
+
 .PHONY: clean
 clean:
 	rm -rf gen
diff --git a/gen/dart-gen/mojom/lib/mojo/examples/echo.mojom.dart b/gen/dart-gen/mojom/lib/mojo/examples/echo.mojom.dart
deleted file mode 100644
index e50c356..0000000
--- a/gen/dart-gen/mojom/lib/mojo/examples/echo.mojom.dart
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library echo_mojom;
-
-import 'dart:async';
-
-import 'package:mojo/bindings.dart' as bindings;
-import 'package:mojo/core.dart' as core;
-
-
-class EchoEchoStringParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String value = null;
-
-  EchoEchoStringParams() : super(kVersions.last.size);
-
-  static EchoEchoStringParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static EchoEchoStringParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    EchoEchoStringParams result = new EchoEchoStringParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.value = decoder0.decodeString(8, true);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(value, 8, true);
-  }
-
-  String toString() {
-    return "EchoEchoStringParams("
-           "value: $value" ")";
-  }
-}
-
-class EchoEchoStringResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String value = null;
-
-  EchoEchoStringResponseParams() : super(kVersions.last.size);
-
-  static EchoEchoStringResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static EchoEchoStringResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    EchoEchoStringResponseParams result = new EchoEchoStringResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.value = decoder0.decodeString(8, true);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(value, 8, true);
-  }
-
-  String toString() {
-    return "EchoEchoStringResponseParams("
-           "value: $value" ")";
-  }
-}
-
-const int kEcho_echoString_name = 0;
-
-const String EchoName =
-      'mojo::examples::Echo';
-
-abstract class Echo {
-  Future<EchoEchoStringResponseParams> echoString(String value,[Function responseFactory = null]);
-
-}
-
-
-class EchoProxyImpl extends bindings.Proxy {
-  EchoProxyImpl.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
-
-  EchoProxyImpl.fromHandle(core.MojoHandle handle) :
-      super.fromHandle(handle);
-
-  EchoProxyImpl.unbound() : super.unbound();
-
-  static EchoProxyImpl newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For EchoProxyImpl"));
-    return new EchoProxyImpl.fromEndpoint(endpoint);
-  }
-
-  String get name => EchoName;
-
-  void handleResponse(bindings.ServiceMessage message) {
-    switch (message.header.type) {
-      case kEcho_echoString_name:
-        var r = EchoEchoStringResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      default:
-        throw new bindings.MojoCodecError("Unexpected message name");
-        break;
-    }
-  }
-
-  String toString() {
-    var superString = super.toString();
-    return "EchoProxyImpl($superString)";
-  }
-}
-
-
-class _EchoProxyCalls implements Echo {
-  EchoProxyImpl _proxyImpl;
-
-  _EchoProxyCalls(this._proxyImpl);
-    Future<EchoEchoStringResponseParams> echoString(String value,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new EchoEchoStringParams();
-      params.value = value;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kEcho_echoString_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-}
-
-
-class EchoProxy implements bindings.ProxyBase {
-  final bindings.Proxy impl;
-  Echo ptr;
-  final String name = EchoName;
-
-  EchoProxy(EchoProxyImpl proxyImpl) :
-      impl = proxyImpl,
-      ptr = new _EchoProxyCalls(proxyImpl);
-
-  EchoProxy.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) :
-      impl = new EchoProxyImpl.fromEndpoint(endpoint) {
-    ptr = new _EchoProxyCalls(impl);
-  }
-
-  EchoProxy.fromHandle(core.MojoHandle handle) :
-      impl = new EchoProxyImpl.fromHandle(handle) {
-    ptr = new _EchoProxyCalls(impl);
-  }
-
-  EchoProxy.unbound() :
-      impl = new EchoProxyImpl.unbound() {
-    ptr = new _EchoProxyCalls(impl);
-  }
-
-  static EchoProxy newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For EchoProxy"));
-    return new EchoProxy.fromEndpoint(endpoint);
-  }
-
-  Future close({bool immediate: false}) => impl.close(immediate: immediate);
-
-  int get version => impl.version;
-
-  Future<int> queryVersion() => impl.queryVersion();
-
-  void requireVersion(int requiredVersion) {
-    impl.requireVersion(requiredVersion);
-  }
-
-  String toString() {
-    return "EchoProxy($impl)";
-  }
-}
-
-
-class EchoStub extends bindings.Stub {
-  Echo _impl = null;
-
-  EchoStub.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint, [this._impl])
-      : super.fromEndpoint(endpoint);
-
-  EchoStub.fromHandle(core.MojoHandle handle, [this._impl])
-      : super.fromHandle(handle);
-
-  EchoStub.unbound() : super.unbound();
-
-  static EchoStub newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For EchoStub"));
-    return new EchoStub.fromEndpoint(endpoint);
-  }
-
-  static const String name = EchoName;
-
-
-  EchoEchoStringResponseParams _EchoEchoStringResponseParamsFactory(String value) {
-    var result = new EchoEchoStringResponseParams();
-    result.value = value;
-    return result;
-  }
-
-  Future<bindings.Message> handleMessage(bindings.ServiceMessage message) {
-    if (bindings.ControlMessageHandler.isControlMessage(message)) {
-      return bindings.ControlMessageHandler.handleMessage(this,
-                                                          0,
-                                                          message);
-    }
-    assert(_impl != null);
-    switch (message.header.type) {
-      case kEcho_echoString_name:
-        var params = EchoEchoStringParams.deserialize(
-            message.payload);
-        return _impl.echoString(params.value,_EchoEchoStringResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kEcho_echoString_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      default:
-        throw new bindings.MojoCodecError("Unexpected message name");
-        break;
-    }
-    return null;
-  }
-
-  Echo get impl => _impl;
-  set impl(Echo d) {
-    assert(_impl == null);
-    _impl = d;
-  }
-
-  String toString() {
-    var superString = super.toString();
-    return "EchoStub($superString)";
-  }
-
-  int get version => 0;
-}
-
-
diff --git a/gen/dart-gen/mojom/lib/mojo/syncbase/syncbase.mojom.dart b/gen/dart-gen/mojom/lib/mojo/syncbase/syncbase.mojom.dart
deleted file mode 100644
index c88c4c7..0000000
--- a/gen/dart-gen/mojom/lib/mojo/syncbase/syncbase.mojom.dart
+++ /dev/null
@@ -1,7098 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library syncbase_mojom;
-
-import 'dart:async';
-
-import 'package:mojo/bindings.dart' as bindings;
-import 'package:mojo/core.dart' as core;
-
-
-class Error extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String id = null;
-  int actionCode = 0;
-  String msg = null;
-
-  Error() : super(kVersions.last.size);
-
-  static Error deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static Error decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    Error result = new Error();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.id = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.actionCode = decoder0.decodeUint32(16);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.msg = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(id, 8, false);
-    
-    encoder0.encodeUint32(actionCode, 16);
-    
-    encoder0.encodeString(msg, 24, false);
-  }
-
-  String toString() {
-    return "Error("
-           "id: $id" ", "
-           "actionCode: $actionCode" ", "
-           "msg: $msg" ")";
-  }
-}
-
-class Perms extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String json = null;
-
-  Perms() : super(kVersions.last.size);
-
-  static Perms deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static Perms decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    Perms result = new Perms();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.json = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(json, 8, false);
-  }
-
-  String toString() {
-    return "Perms("
-           "json: $json" ")";
-  }
-}
-
-class BatchOptions extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String hint = null;
-  bool readOnly = false;
-
-  BatchOptions() : super(kVersions.last.size);
-
-  static BatchOptions deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static BatchOptions decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    BatchOptions result = new BatchOptions();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.hint = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.readOnly = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(hint, 8, false);
-    
-    encoder0.encodeBool(readOnly, 16, 0);
-  }
-
-  String toString() {
-    return "BatchOptions("
-           "hint: $hint" ", "
-           "readOnly: $readOnly" ")";
-  }
-}
-
-class PrefixPerms extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String prefix = null;
-  Perms perms = null;
-
-  PrefixPerms() : super(kVersions.last.size);
-
-  static PrefixPerms deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static PrefixPerms decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    PrefixPerms result = new PrefixPerms();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.prefix = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(prefix, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-  }
-
-  String toString() {
-    return "PrefixPerms("
-           "prefix: $prefix" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncGroupSpec extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(48, 0)
-  ];
-  String description = null;
-  Perms perms = null;
-  List<String> prefixes = null;
-  List<String> mountTables = null;
-  bool isPrivate = false;
-
-  SyncGroupSpec() : super(kVersions.last.size);
-
-  static SyncGroupSpec deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncGroupSpec decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncGroupSpec result = new SyncGroupSpec();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.description = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.prefixes = new List<String>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          result.prefixes[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(32, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.mountTables = new List<String>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          result.mountTables[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.isPrivate = decoder0.decodeBool(40, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(description, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    if (prefixes == null) {
-      encoder0.encodeNullPointer(24, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(prefixes.length, 24, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < prefixes.length; ++i0) {
-        
-        encoder1.encodeString(prefixes[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-    
-    if (mountTables == null) {
-      encoder0.encodeNullPointer(32, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(mountTables.length, 32, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < mountTables.length; ++i0) {
-        
-        encoder1.encodeString(mountTables[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-    
-    encoder0.encodeBool(isPrivate, 40, 0);
-  }
-
-  String toString() {
-    return "SyncGroupSpec("
-           "description: $description" ", "
-           "perms: $perms" ", "
-           "prefixes: $prefixes" ", "
-           "mountTables: $mountTables" ", "
-           "isPrivate: $isPrivate" ")";
-  }
-}
-
-class SyncGroupMemberInfo extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  int syncPriority = 0;
-
-  SyncGroupMemberInfo() : super(kVersions.last.size);
-
-  static SyncGroupMemberInfo deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncGroupMemberInfo decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncGroupMemberInfo result = new SyncGroupMemberInfo();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.syncPriority = decoder0.decodeUint8(8);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeUint8(syncPriority, 8);
-  }
-
-  String toString() {
-    return "SyncGroupMemberInfo("
-           "syncPriority: $syncPriority" ")";
-  }
-}
-
-class SyncbaseServiceGetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(8, 0)
-  ];
-
-  SyncbaseServiceGetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseServiceGetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseServiceGetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseServiceGetPermissionsParams result = new SyncbaseServiceGetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    encoder.getStructEncoderAtOffset(kVersions.last);
-  }
-
-  String toString() {
-    return "SyncbaseServiceGetPermissionsParams("")";
-  }
-}
-
-class SyncbaseServiceGetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  Error err = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseServiceGetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseServiceGetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseServiceGetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseServiceGetPermissionsResponseParams result = new SyncbaseServiceGetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseServiceGetPermissionsResponseParams("
-           "err: $err" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseServiceSetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseServiceSetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseServiceSetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseServiceSetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseServiceSetPermissionsParams result = new SyncbaseServiceSetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(perms, 8, false);
-    
-    encoder0.encodeString(version, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseServiceSetPermissionsParams("
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseServiceSetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseServiceSetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseServiceSetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseServiceSetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseServiceSetPermissionsResponseParams result = new SyncbaseServiceSetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseServiceSetPermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseAppCreateParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-
-  SyncbaseAppCreateParams() : super(kVersions.last.size);
-
-  static SyncbaseAppCreateParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppCreateParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppCreateParams result = new SyncbaseAppCreateParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppCreateParams("
-           "name: $name" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncbaseAppCreateResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseAppCreateResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppCreateResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppCreateResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppCreateResponseParams result = new SyncbaseAppCreateResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppCreateResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseAppDeleteParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseAppDeleteParams() : super(kVersions.last.size);
-
-  static SyncbaseAppDeleteParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppDeleteParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppDeleteParams result = new SyncbaseAppDeleteParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppDeleteParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseAppDeleteResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseAppDeleteResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppDeleteResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppDeleteResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppDeleteResponseParams result = new SyncbaseAppDeleteResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppDeleteResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseAppExistsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseAppExistsParams() : super(kVersions.last.size);
-
-  static SyncbaseAppExistsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppExistsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppExistsParams result = new SyncbaseAppExistsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppExistsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseAppExistsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  bool exists = false;
-
-  SyncbaseAppExistsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppExistsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppExistsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppExistsResponseParams result = new SyncbaseAppExistsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.exists = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeBool(exists, 16, 0);
-  }
-
-  String toString() {
-    return "SyncbaseAppExistsResponseParams("
-           "err: $err" ", "
-           "exists: $exists" ")";
-  }
-}
-
-class SyncbaseAppGetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseAppGetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseAppGetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppGetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppGetPermissionsParams result = new SyncbaseAppGetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppGetPermissionsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseAppGetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  Error err = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseAppGetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppGetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppGetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppGetPermissionsResponseParams result = new SyncbaseAppGetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppGetPermissionsResponseParams("
-           "err: $err" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseAppSetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseAppSetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseAppSetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppSetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppSetPermissionsParams result = new SyncbaseAppSetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppSetPermissionsParams("
-           "name: $name" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseAppSetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseAppSetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppSetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppSetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppSetPermissionsResponseParams result = new SyncbaseAppSetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppSetPermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbCreateParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-
-  SyncbaseDbCreateParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCreateParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCreateParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCreateParams result = new SyncbaseDbCreateParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCreateParams("
-           "name: $name" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncbaseDbCreateResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbCreateResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCreateResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCreateResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCreateResponseParams result = new SyncbaseDbCreateResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCreateResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbDeleteParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbDeleteParams() : super(kVersions.last.size);
-
-  static SyncbaseDbDeleteParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbDeleteParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbDeleteParams result = new SyncbaseDbDeleteParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbDeleteParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbDeleteResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbDeleteResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbDeleteResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbDeleteResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbDeleteResponseParams result = new SyncbaseDbDeleteResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbDeleteResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbExistsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbExistsParams() : super(kVersions.last.size);
-
-  static SyncbaseDbExistsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbExistsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbExistsParams result = new SyncbaseDbExistsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbExistsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbExistsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  bool exists = false;
-
-  SyncbaseDbExistsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbExistsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbExistsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbExistsResponseParams result = new SyncbaseDbExistsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.exists = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeBool(exists, 16, 0);
-  }
-
-  String toString() {
-    return "SyncbaseDbExistsResponseParams("
-           "err: $err" ", "
-           "exists: $exists" ")";
-  }
-}
-
-class SyncbaseDbExecParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String query = null;
-
-  SyncbaseDbExecParams() : super(kVersions.last.size);
-
-  static SyncbaseDbExecParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbExecParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbExecParams result = new SyncbaseDbExecParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.query = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(query, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbExecParams("
-           "query: $query" ")";
-  }
-}
-
-class SyncbaseDbExecResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbExecResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbExecResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbExecResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbExecResponseParams result = new SyncbaseDbExecResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbExecResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbBeginBatchParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  BatchOptions bo = null;
-
-  SyncbaseDbBeginBatchParams() : super(kVersions.last.size);
-
-  static SyncbaseDbBeginBatchParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbBeginBatchParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbBeginBatchParams result = new SyncbaseDbBeginBatchParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, true);
-      result.bo = BatchOptions.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(bo, 16, true);
-  }
-
-  String toString() {
-    return "SyncbaseDbBeginBatchParams("
-           "name: $name" ", "
-           "bo: $bo" ")";
-  }
-}
-
-class SyncbaseDbBeginBatchResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  String batchDn = null;
-
-  SyncbaseDbBeginBatchResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbBeginBatchResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbBeginBatchResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbBeginBatchResponseParams result = new SyncbaseDbBeginBatchResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.batchDn = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeString(batchDn, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbBeginBatchResponseParams("
-           "err: $err" ", "
-           "batchDn: $batchDn" ")";
-  }
-}
-
-class SyncbaseDbCommitParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbCommitParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCommitParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCommitParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCommitParams result = new SyncbaseDbCommitParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCommitParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbCommitResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbCommitResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCommitResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCommitResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCommitResponseParams result = new SyncbaseDbCommitResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCommitResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbAbortParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbAbortParams() : super(kVersions.last.size);
-
-  static SyncbaseDbAbortParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbAbortParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbAbortParams result = new SyncbaseDbAbortParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbAbortParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbAbortResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbAbortResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbAbortResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbAbortResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbAbortResponseParams result = new SyncbaseDbAbortResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbAbortResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbGetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbGetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetPermissionsParams result = new SyncbaseDbGetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetPermissionsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbGetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  Error err = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseDbGetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetPermissionsResponseParams result = new SyncbaseDbGetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetPermissionsResponseParams("
-           "err: $err" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseDbSetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseDbSetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseDbSetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbSetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbSetPermissionsParams result = new SyncbaseDbSetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbSetPermissionsParams("
-           "name: $name" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseDbSetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbSetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbSetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbSetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbSetPermissionsResponseParams result = new SyncbaseDbSetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbSetPermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupNamesParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbGetSyncGroupNamesParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupNamesParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupNamesParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupNamesParams result = new SyncbaseDbGetSyncGroupNamesParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupNamesParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupNamesResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  List<String> names = null;
-
-  SyncbaseDbGetSyncGroupNamesResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupNamesResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupNamesResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupNamesResponseParams result = new SyncbaseDbGetSyncGroupNamesResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.names = new List<String>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          result.names[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    if (names == null) {
-      encoder0.encodeNullPointer(16, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(names.length, 16, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < names.length; ++i0) {
-        
-        encoder1.encodeString(names[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupNamesResponseParams("
-           "err: $err" ", "
-           "names: $names" ")";
-  }
-}
-
-class SyncbaseDbCreateSyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(40, 0)
-  ];
-  String name = null;
-  String sgName = null;
-  SyncGroupSpec spec = null;
-  SyncGroupMemberInfo myInfo = null;
-
-  SyncbaseDbCreateSyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCreateSyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCreateSyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCreateSyncGroupParams result = new SyncbaseDbCreateSyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      result.spec = SyncGroupSpec.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(32, false);
-      result.myInfo = SyncGroupMemberInfo.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-    
-    encoder0.encodeStruct(spec, 24, false);
-    
-    encoder0.encodeStruct(myInfo, 32, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCreateSyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ", "
-           "spec: $spec" ", "
-           "myInfo: $myInfo" ")";
-  }
-}
-
-class SyncbaseDbCreateSyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbCreateSyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCreateSyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCreateSyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCreateSyncGroupResponseParams result = new SyncbaseDbCreateSyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCreateSyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbJoinSyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  String sgName = null;
-  SyncGroupMemberInfo myInfo = null;
-
-  SyncbaseDbJoinSyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbJoinSyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbJoinSyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbJoinSyncGroupParams result = new SyncbaseDbJoinSyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      result.myInfo = SyncGroupMemberInfo.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-    
-    encoder0.encodeStruct(myInfo, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbJoinSyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ", "
-           "myInfo: $myInfo" ")";
-  }
-}
-
-class SyncbaseDbJoinSyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbJoinSyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbJoinSyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbJoinSyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbJoinSyncGroupResponseParams result = new SyncbaseDbJoinSyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbJoinSyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbLeaveSyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String sgName = null;
-
-  SyncbaseDbLeaveSyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbLeaveSyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbLeaveSyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbLeaveSyncGroupParams result = new SyncbaseDbLeaveSyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbLeaveSyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ")";
-  }
-}
-
-class SyncbaseDbLeaveSyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbLeaveSyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbLeaveSyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbLeaveSyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbLeaveSyncGroupResponseParams result = new SyncbaseDbLeaveSyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbLeaveSyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbDestroySyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String sgName = null;
-
-  SyncbaseDbDestroySyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbDestroySyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbDestroySyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbDestroySyncGroupParams result = new SyncbaseDbDestroySyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbDestroySyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ")";
-  }
-}
-
-class SyncbaseDbDestroySyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbDestroySyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbDestroySyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbDestroySyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbDestroySyncGroupResponseParams result = new SyncbaseDbDestroySyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbDestroySyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbEjectFromSyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  String sgName = null;
-  String member = null;
-
-  SyncbaseDbEjectFromSyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbEjectFromSyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbEjectFromSyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbEjectFromSyncGroupParams result = new SyncbaseDbEjectFromSyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.member = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-    
-    encoder0.encodeString(member, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbEjectFromSyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ", "
-           "member: $member" ")";
-  }
-}
-
-class SyncbaseDbEjectFromSyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbEjectFromSyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbEjectFromSyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbEjectFromSyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbEjectFromSyncGroupResponseParams result = new SyncbaseDbEjectFromSyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbEjectFromSyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupSpecParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String sgName = null;
-
-  SyncbaseDbGetSyncGroupSpecParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupSpecParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupSpecParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupSpecParams result = new SyncbaseDbGetSyncGroupSpecParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupSpecParams("
-           "name: $name" ", "
-           "sgName: $sgName" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupSpecResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  Error err = null;
-  SyncGroupSpec spec = null;
-  String version = null;
-
-  SyncbaseDbGetSyncGroupSpecResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupSpecResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupSpecResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupSpecResponseParams result = new SyncbaseDbGetSyncGroupSpecResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.spec = SyncGroupSpec.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeStruct(spec, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupSpecResponseParams("
-           "err: $err" ", "
-           "spec: $spec" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseDbSetSyncGroupSpecParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(40, 0)
-  ];
-  String name = null;
-  String sgName = null;
-  SyncGroupSpec spec = null;
-  String version = null;
-
-  SyncbaseDbSetSyncGroupSpecParams() : super(kVersions.last.size);
-
-  static SyncbaseDbSetSyncGroupSpecParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbSetSyncGroupSpecParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbSetSyncGroupSpecParams result = new SyncbaseDbSetSyncGroupSpecParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      result.spec = SyncGroupSpec.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(32, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-    
-    encoder0.encodeStruct(spec, 24, false);
-    
-    encoder0.encodeString(version, 32, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbSetSyncGroupSpecParams("
-           "name: $name" ", "
-           "sgName: $sgName" ", "
-           "spec: $spec" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseDbSetSyncGroupSpecResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbSetSyncGroupSpecResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbSetSyncGroupSpecResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbSetSyncGroupSpecResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbSetSyncGroupSpecResponseParams result = new SyncbaseDbSetSyncGroupSpecResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbSetSyncGroupSpecResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupMembersParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String sgName = null;
-
-  SyncbaseDbGetSyncGroupMembersParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupMembersParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupMembersParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupMembersParams result = new SyncbaseDbGetSyncGroupMembersParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupMembersParams("
-           "name: $name" ", "
-           "sgName: $sgName" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupMembersResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  Map<String, SyncGroupMemberInfo> infos = null;
-
-  SyncbaseDbGetSyncGroupMembersResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupMembersResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupMembersResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupMembersResponseParams result = new SyncbaseDbGetSyncGroupMembersResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      {
-        decoder1.decodeDataHeaderForMap();
-        List<String> keys0;
-        List<SyncGroupMemberInfo> values0;
-        {
-          
-          var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize, false);
-          {
-            var si2 = decoder2.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-            keys0 = new List<String>(si2.numElements);
-            for (int i2 = 0; i2 < si2.numElements; ++i2) {
-              
-              keys0[i2] = decoder2.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i2, false);
-            }
-          }
-        }
-        {
-          
-          var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize, false);
-          {
-            var si2 = decoder2.decodeDataHeaderForPointerArray(keys0.length);
-            values0 = new List<SyncGroupMemberInfo>(si2.numElements);
-            for (int i2 = 0; i2 < si2.numElements; ++i2) {
-              
-              var decoder3 = decoder2.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i2, false);
-              values0[i2] = SyncGroupMemberInfo.decode(decoder3);
-            }
-          }
-        }
-        result.infos = new Map<String, SyncGroupMemberInfo>.fromIterables(
-            keys0, values0);
-      }
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    if (infos == null) {
-      encoder0.encodeNullPointer(16, false);
-    } else {
-      var encoder1 = encoder0.encoderForMap(16);
-      int size0 = infos.length;
-      var keys0 = infos.keys.toList();
-      var values0 = infos.values.toList();
-      
-      {
-        var encoder2 = encoder1.encodePointerArray(keys0.length, bindings.ArrayDataHeader.kHeaderSize, bindings.kUnspecifiedArrayLength);
-        for (int i1 = 0; i1 < keys0.length; ++i1) {
-          
-          encoder2.encodeString(keys0[i1], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-      
-      {
-        var encoder2 = encoder1.encodePointerArray(values0.length, bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize, bindings.kUnspecifiedArrayLength);
-        for (int i1 = 0; i1 < values0.length; ++i1) {
-          
-          encoder2.encodeStruct(values0[i1], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupMembersResponseParams("
-           "err: $err" ", "
-           "infos: $infos" ")";
-  }
-}
-
-class SyncbaseTableCreateParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-
-  SyncbaseTableCreateParams() : super(kVersions.last.size);
-
-  static SyncbaseTableCreateParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableCreateParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableCreateParams result = new SyncbaseTableCreateParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableCreateParams("
-           "name: $name" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncbaseTableCreateResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableCreateResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableCreateResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableCreateResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableCreateResponseParams result = new SyncbaseTableCreateResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableCreateResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableDeleteParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseTableDeleteParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeleteParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeleteParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeleteParams result = new SyncbaseTableDeleteParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeleteParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseTableDeleteResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableDeleteResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeleteResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeleteResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeleteResponseParams result = new SyncbaseTableDeleteResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeleteResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableExistsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseTableExistsParams() : super(kVersions.last.size);
-
-  static SyncbaseTableExistsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableExistsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableExistsParams result = new SyncbaseTableExistsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableExistsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseTableExistsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  bool exists = false;
-
-  SyncbaseTableExistsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableExistsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableExistsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableExistsResponseParams result = new SyncbaseTableExistsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.exists = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeBool(exists, 16, 0);
-  }
-
-  String toString() {
-    return "SyncbaseTableExistsResponseParams("
-           "err: $err" ", "
-           "exists: $exists" ")";
-  }
-}
-
-class SyncbaseTableDeleteRowRangeParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  List<int> start = null;
-  List<int> limit = null;
-
-  SyncbaseTableDeleteRowRangeParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeleteRowRangeParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeleteRowRangeParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeleteRowRangeParams result = new SyncbaseTableDeleteRowRangeParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.start = decoder0.decodeUint8Array(16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.limit = decoder0.decodeUint8Array(24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeUint8Array(start, 16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    
-    encoder0.encodeUint8Array(limit, 24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeleteRowRangeParams("
-           "name: $name" ", "
-           "start: $start" ", "
-           "limit: $limit" ")";
-  }
-}
-
-class SyncbaseTableDeleteRowRangeResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableDeleteRowRangeResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeleteRowRangeResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeleteRowRangeResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeleteRowRangeResponseParams result = new SyncbaseTableDeleteRowRangeResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeleteRowRangeResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableScanParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  List<int> start = null;
-  List<int> limit = null;
-
-  SyncbaseTableScanParams() : super(kVersions.last.size);
-
-  static SyncbaseTableScanParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableScanParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableScanParams result = new SyncbaseTableScanParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.start = decoder0.decodeUint8Array(16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.limit = decoder0.decodeUint8Array(24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeUint8Array(start, 16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    
-    encoder0.encodeUint8Array(limit, 24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-  }
-
-  String toString() {
-    return "SyncbaseTableScanParams("
-           "name: $name" ", "
-           "start: $start" ", "
-           "limit: $limit" ")";
-  }
-}
-
-class SyncbaseTableScanResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableScanResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableScanResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableScanResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableScanResponseParams result = new SyncbaseTableScanResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableScanResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableGetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String key = null;
-
-  SyncbaseTableGetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseTableGetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableGetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableGetPermissionsParams result = new SyncbaseTableGetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.key = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(key, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableGetPermissionsParams("
-           "name: $name" ", "
-           "key: $key" ")";
-  }
-}
-
-class SyncbaseTableGetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  List<PrefixPerms> permsArr = null;
-
-  SyncbaseTableGetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableGetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableGetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableGetPermissionsResponseParams result = new SyncbaseTableGetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.permsArr = new List<PrefixPerms>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-          result.permsArr[i1] = PrefixPerms.decode(decoder2);
-        }
-      }
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    if (permsArr == null) {
-      encoder0.encodeNullPointer(16, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(permsArr.length, 16, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < permsArr.length; ++i0) {
-        
-        encoder1.encodeStruct(permsArr[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-  }
-
-  String toString() {
-    return "SyncbaseTableGetPermissionsResponseParams("
-           "err: $err" ", "
-           "permsArr: $permsArr" ")";
-  }
-}
-
-class SyncbaseTableSetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  String prefix = null;
-  Perms perms = null;
-
-  SyncbaseTableSetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseTableSetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableSetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableSetPermissionsParams result = new SyncbaseTableSetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.prefix = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(prefix, 16, false);
-    
-    encoder0.encodeStruct(perms, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableSetPermissionsParams("
-           "name: $name" ", "
-           "prefix: $prefix" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncbaseTableSetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableSetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableSetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableSetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableSetPermissionsResponseParams result = new SyncbaseTableSetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableSetPermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableDeletePermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String prefix = null;
-
-  SyncbaseTableDeletePermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeletePermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeletePermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeletePermissionsParams result = new SyncbaseTableDeletePermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.prefix = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(prefix, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeletePermissionsParams("
-           "name: $name" ", "
-           "prefix: $prefix" ")";
-  }
-}
-
-class SyncbaseTableDeletePermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableDeletePermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeletePermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeletePermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeletePermissionsResponseParams result = new SyncbaseTableDeletePermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeletePermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseRowExistsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseRowExistsParams() : super(kVersions.last.size);
-
-  static SyncbaseRowExistsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowExistsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowExistsParams result = new SyncbaseRowExistsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowExistsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseRowExistsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  bool exists = false;
-
-  SyncbaseRowExistsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseRowExistsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowExistsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowExistsResponseParams result = new SyncbaseRowExistsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.exists = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeBool(exists, 16, 0);
-  }
-
-  String toString() {
-    return "SyncbaseRowExistsResponseParams("
-           "err: $err" ", "
-           "exists: $exists" ")";
-  }
-}
-
-class SyncbaseRowGetParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseRowGetParams() : super(kVersions.last.size);
-
-  static SyncbaseRowGetParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowGetParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowGetParams result = new SyncbaseRowGetParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowGetParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseRowGetResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  List<int> value = null;
-
-  SyncbaseRowGetResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseRowGetResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowGetResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowGetResponseParams result = new SyncbaseRowGetResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.value = decoder0.decodeUint8Array(16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeUint8Array(value, 16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-  }
-
-  String toString() {
-    return "SyncbaseRowGetResponseParams("
-           "err: $err" ", "
-           "value: $value" ")";
-  }
-}
-
-class SyncbaseRowPutParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  List<int> value = null;
-
-  SyncbaseRowPutParams() : super(kVersions.last.size);
-
-  static SyncbaseRowPutParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowPutParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowPutParams result = new SyncbaseRowPutParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.value = decoder0.decodeUint8Array(16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeUint8Array(value, 16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-  }
-
-  String toString() {
-    return "SyncbaseRowPutParams("
-           "name: $name" ", "
-           "value: $value" ")";
-  }
-}
-
-class SyncbaseRowPutResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseRowPutResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseRowPutResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowPutResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowPutResponseParams result = new SyncbaseRowPutResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowPutResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseRowDeleteParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseRowDeleteParams() : super(kVersions.last.size);
-
-  static SyncbaseRowDeleteParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowDeleteParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowDeleteParams result = new SyncbaseRowDeleteParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowDeleteParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseRowDeleteResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseRowDeleteResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseRowDeleteResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowDeleteResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowDeleteResponseParams result = new SyncbaseRowDeleteResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowDeleteResponseParams("
-           "err: $err" ")";
-  }
-}
-
-const int kSyncbase_serviceGetPermissions_name = 0;
-const int kSyncbase_serviceSetPermissions_name = 1;
-const int kSyncbase_appCreate_name = 2;
-const int kSyncbase_appDelete_name = 3;
-const int kSyncbase_appExists_name = 4;
-const int kSyncbase_appGetPermissions_name = 5;
-const int kSyncbase_appSetPermissions_name = 6;
-const int kSyncbase_dbCreate_name = 7;
-const int kSyncbase_dbDelete_name = 8;
-const int kSyncbase_dbExists_name = 9;
-const int kSyncbase_dbExec_name = 10;
-const int kSyncbase_dbBeginBatch_name = 11;
-const int kSyncbase_dbCommit_name = 12;
-const int kSyncbase_dbAbort_name = 13;
-const int kSyncbase_dbGetPermissions_name = 14;
-const int kSyncbase_dbSetPermissions_name = 15;
-const int kSyncbase_dbGetSyncGroupNames_name = 16;
-const int kSyncbase_dbCreateSyncGroup_name = 17;
-const int kSyncbase_dbJoinSyncGroup_name = 18;
-const int kSyncbase_dbLeaveSyncGroup_name = 19;
-const int kSyncbase_dbDestroySyncGroup_name = 20;
-const int kSyncbase_dbEjectFromSyncGroup_name = 21;
-const int kSyncbase_dbGetSyncGroupSpec_name = 22;
-const int kSyncbase_dbSetSyncGroupSpec_name = 23;
-const int kSyncbase_dbGetSyncGroupMembers_name = 24;
-const int kSyncbase_tableCreate_name = 25;
-const int kSyncbase_tableDelete_name = 26;
-const int kSyncbase_tableExists_name = 27;
-const int kSyncbase_tableDeleteRowRange_name = 28;
-const int kSyncbase_tableScan_name = 29;
-const int kSyncbase_tableGetPermissions_name = 30;
-const int kSyncbase_tableSetPermissions_name = 31;
-const int kSyncbase_tableDeletePermissions_name = 32;
-const int kSyncbase_rowExists_name = 33;
-const int kSyncbase_rowGet_name = 34;
-const int kSyncbase_rowPut_name = 35;
-const int kSyncbase_rowDelete_name = 36;
-
-const String SyncbaseName =
-      'mojo::syncbase::Syncbase';
-
-abstract class Syncbase {
-  Future<SyncbaseServiceGetPermissionsResponseParams> serviceGetPermissions([Function responseFactory = null]);
-  Future<SyncbaseServiceSetPermissionsResponseParams> serviceSetPermissions(Perms perms,String version,[Function responseFactory = null]);
-  Future<SyncbaseAppCreateResponseParams> appCreate(String name,Perms perms,[Function responseFactory = null]);
-  Future<SyncbaseAppDeleteResponseParams> appDelete(String name,[Function responseFactory = null]);
-  Future<SyncbaseAppExistsResponseParams> appExists(String name,[Function responseFactory = null]);
-  Future<SyncbaseAppGetPermissionsResponseParams> appGetPermissions(String name,[Function responseFactory = null]);
-  Future<SyncbaseAppSetPermissionsResponseParams> appSetPermissions(String name,Perms perms,String version,[Function responseFactory = null]);
-  Future<SyncbaseDbCreateResponseParams> dbCreate(String name,Perms perms,[Function responseFactory = null]);
-  Future<SyncbaseDbDeleteResponseParams> dbDelete(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbExistsResponseParams> dbExists(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbExecResponseParams> dbExec(String query,[Function responseFactory = null]);
-  Future<SyncbaseDbBeginBatchResponseParams> dbBeginBatch(String name,BatchOptions bo,[Function responseFactory = null]);
-  Future<SyncbaseDbCommitResponseParams> dbCommit(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbAbortResponseParams> dbAbort(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbGetPermissionsResponseParams> dbGetPermissions(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbSetPermissionsResponseParams> dbSetPermissions(String name,Perms perms,String version,[Function responseFactory = null]);
-  Future<SyncbaseDbGetSyncGroupNamesResponseParams> dbGetSyncGroupNames(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbCreateSyncGroupResponseParams> dbCreateSyncGroup(String name,String sgName,SyncGroupSpec spec,SyncGroupMemberInfo myInfo,[Function responseFactory = null]);
-  Future<SyncbaseDbJoinSyncGroupResponseParams> dbJoinSyncGroup(String name,String sgName,SyncGroupMemberInfo myInfo,[Function responseFactory = null]);
-  Future<SyncbaseDbLeaveSyncGroupResponseParams> dbLeaveSyncGroup(String name,String sgName,[Function responseFactory = null]);
-  Future<SyncbaseDbDestroySyncGroupResponseParams> dbDestroySyncGroup(String name,String sgName,[Function responseFactory = null]);
-  Future<SyncbaseDbEjectFromSyncGroupResponseParams> dbEjectFromSyncGroup(String name,String sgName,String member,[Function responseFactory = null]);
-  Future<SyncbaseDbGetSyncGroupSpecResponseParams> dbGetSyncGroupSpec(String name,String sgName,[Function responseFactory = null]);
-  Future<SyncbaseDbSetSyncGroupSpecResponseParams> dbSetSyncGroupSpec(String name,String sgName,SyncGroupSpec spec,String version,[Function responseFactory = null]);
-  Future<SyncbaseDbGetSyncGroupMembersResponseParams> dbGetSyncGroupMembers(String name,String sgName,[Function responseFactory = null]);
-  Future<SyncbaseTableCreateResponseParams> tableCreate(String name,Perms perms,[Function responseFactory = null]);
-  Future<SyncbaseTableDeleteResponseParams> tableDelete(String name,[Function responseFactory = null]);
-  Future<SyncbaseTableExistsResponseParams> tableExists(String name,[Function responseFactory = null]);
-  Future<SyncbaseTableDeleteRowRangeResponseParams> tableDeleteRowRange(String name,List<int> start,List<int> limit,[Function responseFactory = null]);
-  Future<SyncbaseTableScanResponseParams> tableScan(String name,List<int> start,List<int> limit,[Function responseFactory = null]);
-  Future<SyncbaseTableGetPermissionsResponseParams> tableGetPermissions(String name,String key,[Function responseFactory = null]);
-  Future<SyncbaseTableSetPermissionsResponseParams> tableSetPermissions(String name,String prefix,Perms perms,[Function responseFactory = null]);
-  Future<SyncbaseTableDeletePermissionsResponseParams> tableDeletePermissions(String name,String prefix,[Function responseFactory = null]);
-  Future<SyncbaseRowExistsResponseParams> rowExists(String name,[Function responseFactory = null]);
-  Future<SyncbaseRowGetResponseParams> rowGet(String name,[Function responseFactory = null]);
-  Future<SyncbaseRowPutResponseParams> rowPut(String name,List<int> value,[Function responseFactory = null]);
-  Future<SyncbaseRowDeleteResponseParams> rowDelete(String name,[Function responseFactory = null]);
-
-}
-
-
-class SyncbaseProxyImpl extends bindings.Proxy {
-  SyncbaseProxyImpl.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
-
-  SyncbaseProxyImpl.fromHandle(core.MojoHandle handle) :
-      super.fromHandle(handle);
-
-  SyncbaseProxyImpl.unbound() : super.unbound();
-
-  static SyncbaseProxyImpl newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For SyncbaseProxyImpl"));
-    return new SyncbaseProxyImpl.fromEndpoint(endpoint);
-  }
-
-  String get name => SyncbaseName;
-
-  void handleResponse(bindings.ServiceMessage message) {
-    switch (message.header.type) {
-      case kSyncbase_serviceGetPermissions_name:
-        var r = SyncbaseServiceGetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_serviceSetPermissions_name:
-        var r = SyncbaseServiceSetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appCreate_name:
-        var r = SyncbaseAppCreateResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appDelete_name:
-        var r = SyncbaseAppDeleteResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appExists_name:
-        var r = SyncbaseAppExistsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appGetPermissions_name:
-        var r = SyncbaseAppGetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appSetPermissions_name:
-        var r = SyncbaseAppSetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbCreate_name:
-        var r = SyncbaseDbCreateResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbDelete_name:
-        var r = SyncbaseDbDeleteResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbExists_name:
-        var r = SyncbaseDbExistsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbExec_name:
-        var r = SyncbaseDbExecResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbBeginBatch_name:
-        var r = SyncbaseDbBeginBatchResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbCommit_name:
-        var r = SyncbaseDbCommitResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbAbort_name:
-        var r = SyncbaseDbAbortResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbGetPermissions_name:
-        var r = SyncbaseDbGetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbSetPermissions_name:
-        var r = SyncbaseDbSetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbGetSyncGroupNames_name:
-        var r = SyncbaseDbGetSyncGroupNamesResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbCreateSyncGroup_name:
-        var r = SyncbaseDbCreateSyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbJoinSyncGroup_name:
-        var r = SyncbaseDbJoinSyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbLeaveSyncGroup_name:
-        var r = SyncbaseDbLeaveSyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbDestroySyncGroup_name:
-        var r = SyncbaseDbDestroySyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbEjectFromSyncGroup_name:
-        var r = SyncbaseDbEjectFromSyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbGetSyncGroupSpec_name:
-        var r = SyncbaseDbGetSyncGroupSpecResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbSetSyncGroupSpec_name:
-        var r = SyncbaseDbSetSyncGroupSpecResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbGetSyncGroupMembers_name:
-        var r = SyncbaseDbGetSyncGroupMembersResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableCreate_name:
-        var r = SyncbaseTableCreateResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableDelete_name:
-        var r = SyncbaseTableDeleteResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableExists_name:
-        var r = SyncbaseTableExistsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableDeleteRowRange_name:
-        var r = SyncbaseTableDeleteRowRangeResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableScan_name:
-        var r = SyncbaseTableScanResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableGetPermissions_name:
-        var r = SyncbaseTableGetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableSetPermissions_name:
-        var r = SyncbaseTableSetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableDeletePermissions_name:
-        var r = SyncbaseTableDeletePermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_rowExists_name:
-        var r = SyncbaseRowExistsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_rowGet_name:
-        var r = SyncbaseRowGetResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_rowPut_name:
-        var r = SyncbaseRowPutResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_rowDelete_name:
-        var r = SyncbaseRowDeleteResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      default:
-        throw new bindings.MojoCodecError("Unexpected message name");
-        break;
-    }
-  }
-
-  String toString() {
-    var superString = super.toString();
-    return "SyncbaseProxyImpl($superString)";
-  }
-}
-
-
-class _SyncbaseProxyCalls implements Syncbase {
-  SyncbaseProxyImpl _proxyImpl;
-
-  _SyncbaseProxyCalls(this._proxyImpl);
-    Future<SyncbaseServiceGetPermissionsResponseParams> serviceGetPermissions([Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseServiceGetPermissionsParams();
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_serviceGetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseServiceSetPermissionsResponseParams> serviceSetPermissions(Perms perms,String version,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseServiceSetPermissionsParams();
-      params.perms = perms;
-      params.version = version;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_serviceSetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppCreateResponseParams> appCreate(String name,Perms perms,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppCreateParams();
-      params.name = name;
-      params.perms = perms;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appCreate_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppDeleteResponseParams> appDelete(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppDeleteParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appDelete_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppExistsResponseParams> appExists(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppExistsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appExists_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppGetPermissionsResponseParams> appGetPermissions(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppGetPermissionsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appGetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppSetPermissionsResponseParams> appSetPermissions(String name,Perms perms,String version,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppSetPermissionsParams();
-      params.name = name;
-      params.perms = perms;
-      params.version = version;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appSetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbCreateResponseParams> dbCreate(String name,Perms perms,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbCreateParams();
-      params.name = name;
-      params.perms = perms;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbCreate_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbDeleteResponseParams> dbDelete(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbDeleteParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbDelete_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbExistsResponseParams> dbExists(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbExistsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbExists_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbExecResponseParams> dbExec(String query,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbExecParams();
-      params.query = query;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbExec_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbBeginBatchResponseParams> dbBeginBatch(String name,BatchOptions bo,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbBeginBatchParams();
-      params.name = name;
-      params.bo = bo;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbBeginBatch_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbCommitResponseParams> dbCommit(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbCommitParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbCommit_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbAbortResponseParams> dbAbort(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbAbortParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbAbort_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbGetPermissionsResponseParams> dbGetPermissions(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbGetPermissionsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbGetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbSetPermissionsResponseParams> dbSetPermissions(String name,Perms perms,String version,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbSetPermissionsParams();
-      params.name = name;
-      params.perms = perms;
-      params.version = version;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbSetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbGetSyncGroupNamesResponseParams> dbGetSyncGroupNames(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbGetSyncGroupNamesParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbGetSyncGroupNames_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbCreateSyncGroupResponseParams> dbCreateSyncGroup(String name,String sgName,SyncGroupSpec spec,SyncGroupMemberInfo myInfo,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbCreateSyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      params.spec = spec;
-      params.myInfo = myInfo;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbCreateSyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbJoinSyncGroupResponseParams> dbJoinSyncGroup(String name,String sgName,SyncGroupMemberInfo myInfo,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbJoinSyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      params.myInfo = myInfo;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbJoinSyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbLeaveSyncGroupResponseParams> dbLeaveSyncGroup(String name,String sgName,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbLeaveSyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbLeaveSyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbDestroySyncGroupResponseParams> dbDestroySyncGroup(String name,String sgName,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbDestroySyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbDestroySyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbEjectFromSyncGroupResponseParams> dbEjectFromSyncGroup(String name,String sgName,String member,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbEjectFromSyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      params.member = member;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbEjectFromSyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbGetSyncGroupSpecResponseParams> dbGetSyncGroupSpec(String name,String sgName,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbGetSyncGroupSpecParams();
-      params.name = name;
-      params.sgName = sgName;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbGetSyncGroupSpec_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbSetSyncGroupSpecResponseParams> dbSetSyncGroupSpec(String name,String sgName,SyncGroupSpec spec,String version,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbSetSyncGroupSpecParams();
-      params.name = name;
-      params.sgName = sgName;
-      params.spec = spec;
-      params.version = version;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbSetSyncGroupSpec_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbGetSyncGroupMembersResponseParams> dbGetSyncGroupMembers(String name,String sgName,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbGetSyncGroupMembersParams();
-      params.name = name;
-      params.sgName = sgName;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbGetSyncGroupMembers_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableCreateResponseParams> tableCreate(String name,Perms perms,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableCreateParams();
-      params.name = name;
-      params.perms = perms;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableCreate_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableDeleteResponseParams> tableDelete(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableDeleteParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableDelete_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableExistsResponseParams> tableExists(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableExistsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableExists_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableDeleteRowRangeResponseParams> tableDeleteRowRange(String name,List<int> start,List<int> limit,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableDeleteRowRangeParams();
-      params.name = name;
-      params.start = start;
-      params.limit = limit;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableDeleteRowRange_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableScanResponseParams> tableScan(String name,List<int> start,List<int> limit,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableScanParams();
-      params.name = name;
-      params.start = start;
-      params.limit = limit;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableScan_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableGetPermissionsResponseParams> tableGetPermissions(String name,String key,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableGetPermissionsParams();
-      params.name = name;
-      params.key = key;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableGetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableSetPermissionsResponseParams> tableSetPermissions(String name,String prefix,Perms perms,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableSetPermissionsParams();
-      params.name = name;
-      params.prefix = prefix;
-      params.perms = perms;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableSetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableDeletePermissionsResponseParams> tableDeletePermissions(String name,String prefix,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableDeletePermissionsParams();
-      params.name = name;
-      params.prefix = prefix;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableDeletePermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseRowExistsResponseParams> rowExists(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseRowExistsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_rowExists_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseRowGetResponseParams> rowGet(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseRowGetParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_rowGet_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseRowPutResponseParams> rowPut(String name,List<int> value,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseRowPutParams();
-      params.name = name;
-      params.value = value;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_rowPut_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseRowDeleteResponseParams> rowDelete(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseRowDeleteParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_rowDelete_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-}
-
-
-class SyncbaseProxy implements bindings.ProxyBase {
-  final bindings.Proxy impl;
-  Syncbase ptr;
-  final String name = SyncbaseName;
-
-  SyncbaseProxy(SyncbaseProxyImpl proxyImpl) :
-      impl = proxyImpl,
-      ptr = new _SyncbaseProxyCalls(proxyImpl);
-
-  SyncbaseProxy.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) :
-      impl = new SyncbaseProxyImpl.fromEndpoint(endpoint) {
-    ptr = new _SyncbaseProxyCalls(impl);
-  }
-
-  SyncbaseProxy.fromHandle(core.MojoHandle handle) :
-      impl = new SyncbaseProxyImpl.fromHandle(handle) {
-    ptr = new _SyncbaseProxyCalls(impl);
-  }
-
-  SyncbaseProxy.unbound() :
-      impl = new SyncbaseProxyImpl.unbound() {
-    ptr = new _SyncbaseProxyCalls(impl);
-  }
-
-  static SyncbaseProxy newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For SyncbaseProxy"));
-    return new SyncbaseProxy.fromEndpoint(endpoint);
-  }
-
-  Future close({bool immediate: false}) => impl.close(immediate: immediate);
-
-  int get version => impl.version;
-
-  Future<int> queryVersion() => impl.queryVersion();
-
-  void requireVersion(int requiredVersion) {
-    impl.requireVersion(requiredVersion);
-  }
-
-  String toString() {
-    return "SyncbaseProxy($impl)";
-  }
-}
-
-
-class SyncbaseStub extends bindings.Stub {
-  Syncbase _impl = null;
-
-  SyncbaseStub.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint, [this._impl])
-      : super.fromEndpoint(endpoint);
-
-  SyncbaseStub.fromHandle(core.MojoHandle handle, [this._impl])
-      : super.fromHandle(handle);
-
-  SyncbaseStub.unbound() : super.unbound();
-
-  static SyncbaseStub newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For SyncbaseStub"));
-    return new SyncbaseStub.fromEndpoint(endpoint);
-  }
-
-  static const String name = SyncbaseName;
-
-
-  SyncbaseServiceGetPermissionsResponseParams _SyncbaseServiceGetPermissionsResponseParamsFactory(Error err, Perms perms, String version) {
-    var result = new SyncbaseServiceGetPermissionsResponseParams();
-    result.err = err;
-    result.perms = perms;
-    result.version = version;
-    return result;
-  }
-  SyncbaseServiceSetPermissionsResponseParams _SyncbaseServiceSetPermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseServiceSetPermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseAppCreateResponseParams _SyncbaseAppCreateResponseParamsFactory(Error err) {
-    var result = new SyncbaseAppCreateResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseAppDeleteResponseParams _SyncbaseAppDeleteResponseParamsFactory(Error err) {
-    var result = new SyncbaseAppDeleteResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseAppExistsResponseParams _SyncbaseAppExistsResponseParamsFactory(Error err, bool exists) {
-    var result = new SyncbaseAppExistsResponseParams();
-    result.err = err;
-    result.exists = exists;
-    return result;
-  }
-  SyncbaseAppGetPermissionsResponseParams _SyncbaseAppGetPermissionsResponseParamsFactory(Error err, Perms perms, String version) {
-    var result = new SyncbaseAppGetPermissionsResponseParams();
-    result.err = err;
-    result.perms = perms;
-    result.version = version;
-    return result;
-  }
-  SyncbaseAppSetPermissionsResponseParams _SyncbaseAppSetPermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseAppSetPermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbCreateResponseParams _SyncbaseDbCreateResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbCreateResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbDeleteResponseParams _SyncbaseDbDeleteResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbDeleteResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbExistsResponseParams _SyncbaseDbExistsResponseParamsFactory(Error err, bool exists) {
-    var result = new SyncbaseDbExistsResponseParams();
-    result.err = err;
-    result.exists = exists;
-    return result;
-  }
-  SyncbaseDbExecResponseParams _SyncbaseDbExecResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbExecResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbBeginBatchResponseParams _SyncbaseDbBeginBatchResponseParamsFactory(Error err, String batchDn) {
-    var result = new SyncbaseDbBeginBatchResponseParams();
-    result.err = err;
-    result.batchDn = batchDn;
-    return result;
-  }
-  SyncbaseDbCommitResponseParams _SyncbaseDbCommitResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbCommitResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbAbortResponseParams _SyncbaseDbAbortResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbAbortResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbGetPermissionsResponseParams _SyncbaseDbGetPermissionsResponseParamsFactory(Error err, Perms perms, String version) {
-    var result = new SyncbaseDbGetPermissionsResponseParams();
-    result.err = err;
-    result.perms = perms;
-    result.version = version;
-    return result;
-  }
-  SyncbaseDbSetPermissionsResponseParams _SyncbaseDbSetPermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbSetPermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbGetSyncGroupNamesResponseParams _SyncbaseDbGetSyncGroupNamesResponseParamsFactory(Error err, List<String> names) {
-    var result = new SyncbaseDbGetSyncGroupNamesResponseParams();
-    result.err = err;
-    result.names = names;
-    return result;
-  }
-  SyncbaseDbCreateSyncGroupResponseParams _SyncbaseDbCreateSyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbCreateSyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbJoinSyncGroupResponseParams _SyncbaseDbJoinSyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbJoinSyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbLeaveSyncGroupResponseParams _SyncbaseDbLeaveSyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbLeaveSyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbDestroySyncGroupResponseParams _SyncbaseDbDestroySyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbDestroySyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbEjectFromSyncGroupResponseParams _SyncbaseDbEjectFromSyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbEjectFromSyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbGetSyncGroupSpecResponseParams _SyncbaseDbGetSyncGroupSpecResponseParamsFactory(Error err, SyncGroupSpec spec, String version) {
-    var result = new SyncbaseDbGetSyncGroupSpecResponseParams();
-    result.err = err;
-    result.spec = spec;
-    result.version = version;
-    return result;
-  }
-  SyncbaseDbSetSyncGroupSpecResponseParams _SyncbaseDbSetSyncGroupSpecResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbSetSyncGroupSpecResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbGetSyncGroupMembersResponseParams _SyncbaseDbGetSyncGroupMembersResponseParamsFactory(Error err, Map<String, SyncGroupMemberInfo> infos) {
-    var result = new SyncbaseDbGetSyncGroupMembersResponseParams();
-    result.err = err;
-    result.infos = infos;
-    return result;
-  }
-  SyncbaseTableCreateResponseParams _SyncbaseTableCreateResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableCreateResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableDeleteResponseParams _SyncbaseTableDeleteResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableDeleteResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableExistsResponseParams _SyncbaseTableExistsResponseParamsFactory(Error err, bool exists) {
-    var result = new SyncbaseTableExistsResponseParams();
-    result.err = err;
-    result.exists = exists;
-    return result;
-  }
-  SyncbaseTableDeleteRowRangeResponseParams _SyncbaseTableDeleteRowRangeResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableDeleteRowRangeResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableScanResponseParams _SyncbaseTableScanResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableScanResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableGetPermissionsResponseParams _SyncbaseTableGetPermissionsResponseParamsFactory(Error err, List<PrefixPerms> permsArr) {
-    var result = new SyncbaseTableGetPermissionsResponseParams();
-    result.err = err;
-    result.permsArr = permsArr;
-    return result;
-  }
-  SyncbaseTableSetPermissionsResponseParams _SyncbaseTableSetPermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableSetPermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableDeletePermissionsResponseParams _SyncbaseTableDeletePermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableDeletePermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseRowExistsResponseParams _SyncbaseRowExistsResponseParamsFactory(Error err, bool exists) {
-    var result = new SyncbaseRowExistsResponseParams();
-    result.err = err;
-    result.exists = exists;
-    return result;
-  }
-  SyncbaseRowGetResponseParams _SyncbaseRowGetResponseParamsFactory(Error err, List<int> value) {
-    var result = new SyncbaseRowGetResponseParams();
-    result.err = err;
-    result.value = value;
-    return result;
-  }
-  SyncbaseRowPutResponseParams _SyncbaseRowPutResponseParamsFactory(Error err) {
-    var result = new SyncbaseRowPutResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseRowDeleteResponseParams _SyncbaseRowDeleteResponseParamsFactory(Error err) {
-    var result = new SyncbaseRowDeleteResponseParams();
-    result.err = err;
-    return result;
-  }
-
-  Future<bindings.Message> handleMessage(bindings.ServiceMessage message) {
-    if (bindings.ControlMessageHandler.isControlMessage(message)) {
-      return bindings.ControlMessageHandler.handleMessage(this,
-                                                          0,
-                                                          message);
-    }
-    assert(_impl != null);
-    switch (message.header.type) {
-      case kSyncbase_serviceGetPermissions_name:
-        var params = SyncbaseServiceGetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.serviceGetPermissions(_SyncbaseServiceGetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_serviceGetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_serviceSetPermissions_name:
-        var params = SyncbaseServiceSetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.serviceSetPermissions(params.perms,params.version,_SyncbaseServiceSetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_serviceSetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appCreate_name:
-        var params = SyncbaseAppCreateParams.deserialize(
-            message.payload);
-        return _impl.appCreate(params.name,params.perms,_SyncbaseAppCreateResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appCreate_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appDelete_name:
-        var params = SyncbaseAppDeleteParams.deserialize(
-            message.payload);
-        return _impl.appDelete(params.name,_SyncbaseAppDeleteResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appDelete_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appExists_name:
-        var params = SyncbaseAppExistsParams.deserialize(
-            message.payload);
-        return _impl.appExists(params.name,_SyncbaseAppExistsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appExists_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appGetPermissions_name:
-        var params = SyncbaseAppGetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.appGetPermissions(params.name,_SyncbaseAppGetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appGetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appSetPermissions_name:
-        var params = SyncbaseAppSetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.appSetPermissions(params.name,params.perms,params.version,_SyncbaseAppSetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appSetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbCreate_name:
-        var params = SyncbaseDbCreateParams.deserialize(
-            message.payload);
-        return _impl.dbCreate(params.name,params.perms,_SyncbaseDbCreateResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbCreate_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbDelete_name:
-        var params = SyncbaseDbDeleteParams.deserialize(
-            message.payload);
-        return _impl.dbDelete(params.name,_SyncbaseDbDeleteResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbDelete_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbExists_name:
-        var params = SyncbaseDbExistsParams.deserialize(
-            message.payload);
-        return _impl.dbExists(params.name,_SyncbaseDbExistsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbExists_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbExec_name:
-        var params = SyncbaseDbExecParams.deserialize(
-            message.payload);
-        return _impl.dbExec(params.query,_SyncbaseDbExecResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbExec_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbBeginBatch_name:
-        var params = SyncbaseDbBeginBatchParams.deserialize(
-            message.payload);
-        return _impl.dbBeginBatch(params.name,params.bo,_SyncbaseDbBeginBatchResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbBeginBatch_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbCommit_name:
-        var params = SyncbaseDbCommitParams.deserialize(
-            message.payload);
-        return _impl.dbCommit(params.name,_SyncbaseDbCommitResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbCommit_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbAbort_name:
-        var params = SyncbaseDbAbortParams.deserialize(
-            message.payload);
-        return _impl.dbAbort(params.name,_SyncbaseDbAbortResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbAbort_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbGetPermissions_name:
-        var params = SyncbaseDbGetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.dbGetPermissions(params.name,_SyncbaseDbGetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbGetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbSetPermissions_name:
-        var params = SyncbaseDbSetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.dbSetPermissions(params.name,params.perms,params.version,_SyncbaseDbSetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbSetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbGetSyncGroupNames_name:
-        var params = SyncbaseDbGetSyncGroupNamesParams.deserialize(
-            message.payload);
-        return _impl.dbGetSyncGroupNames(params.name,_SyncbaseDbGetSyncGroupNamesResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbGetSyncGroupNames_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbCreateSyncGroup_name:
-        var params = SyncbaseDbCreateSyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbCreateSyncGroup(params.name,params.sgName,params.spec,params.myInfo,_SyncbaseDbCreateSyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbCreateSyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbJoinSyncGroup_name:
-        var params = SyncbaseDbJoinSyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbJoinSyncGroup(params.name,params.sgName,params.myInfo,_SyncbaseDbJoinSyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbJoinSyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbLeaveSyncGroup_name:
-        var params = SyncbaseDbLeaveSyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbLeaveSyncGroup(params.name,params.sgName,_SyncbaseDbLeaveSyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbLeaveSyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbDestroySyncGroup_name:
-        var params = SyncbaseDbDestroySyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbDestroySyncGroup(params.name,params.sgName,_SyncbaseDbDestroySyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbDestroySyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbEjectFromSyncGroup_name:
-        var params = SyncbaseDbEjectFromSyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbEjectFromSyncGroup(params.name,params.sgName,params.member,_SyncbaseDbEjectFromSyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbEjectFromSyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbGetSyncGroupSpec_name:
-        var params = SyncbaseDbGetSyncGroupSpecParams.deserialize(
-            message.payload);
-        return _impl.dbGetSyncGroupSpec(params.name,params.sgName,_SyncbaseDbGetSyncGroupSpecResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbGetSyncGroupSpec_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbSetSyncGroupSpec_name:
-        var params = SyncbaseDbSetSyncGroupSpecParams.deserialize(
-            message.payload);
-        return _impl.dbSetSyncGroupSpec(params.name,params.sgName,params.spec,params.version,_SyncbaseDbSetSyncGroupSpecResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbSetSyncGroupSpec_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbGetSyncGroupMembers_name:
-        var params = SyncbaseDbGetSyncGroupMembersParams.deserialize(
-            message.payload);
-        return _impl.dbGetSyncGroupMembers(params.name,params.sgName,_SyncbaseDbGetSyncGroupMembersResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbGetSyncGroupMembers_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableCreate_name:
-        var params = SyncbaseTableCreateParams.deserialize(
-            message.payload);
-        return _impl.tableCreate(params.name,params.perms,_SyncbaseTableCreateResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableCreate_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableDelete_name:
-        var params = SyncbaseTableDeleteParams.deserialize(
-            message.payload);
-        return _impl.tableDelete(params.name,_SyncbaseTableDeleteResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableDelete_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableExists_name:
-        var params = SyncbaseTableExistsParams.deserialize(
-            message.payload);
-        return _impl.tableExists(params.name,_SyncbaseTableExistsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableExists_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableDeleteRowRange_name:
-        var params = SyncbaseTableDeleteRowRangeParams.deserialize(
-            message.payload);
-        return _impl.tableDeleteRowRange(params.name,params.start,params.limit,_SyncbaseTableDeleteRowRangeResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableDeleteRowRange_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableScan_name:
-        var params = SyncbaseTableScanParams.deserialize(
-            message.payload);
-        return _impl.tableScan(params.name,params.start,params.limit,_SyncbaseTableScanResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableScan_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableGetPermissions_name:
-        var params = SyncbaseTableGetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.tableGetPermissions(params.name,params.key,_SyncbaseTableGetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableGetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableSetPermissions_name:
-        var params = SyncbaseTableSetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.tableSetPermissions(params.name,params.prefix,params.perms,_SyncbaseTableSetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableSetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableDeletePermissions_name:
-        var params = SyncbaseTableDeletePermissionsParams.deserialize(
-            message.payload);
-        return _impl.tableDeletePermissions(params.name,params.prefix,_SyncbaseTableDeletePermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableDeletePermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_rowExists_name:
-        var params = SyncbaseRowExistsParams.deserialize(
-            message.payload);
-        return _impl.rowExists(params.name,_SyncbaseRowExistsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_rowExists_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_rowGet_name:
-        var params = SyncbaseRowGetParams.deserialize(
-            message.payload);
-        return _impl.rowGet(params.name,_SyncbaseRowGetResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_rowGet_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_rowPut_name:
-        var params = SyncbaseRowPutParams.deserialize(
-            message.payload);
-        return _impl.rowPut(params.name,params.value,_SyncbaseRowPutResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_rowPut_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_rowDelete_name:
-        var params = SyncbaseRowDeleteParams.deserialize(
-            message.payload);
-        return _impl.rowDelete(params.name,_SyncbaseRowDeleteResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_rowDelete_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      default:
-        throw new bindings.MojoCodecError("Unexpected message name");
-        break;
-    }
-    return null;
-  }
-
-  Syncbase get impl => _impl;
-  set impl(Syncbase d) {
-    assert(_impl == null);
-    _impl = d;
-  }
-
-  String toString() {
-    var superString = super.toString();
-    return "SyncbaseStub($superString)";
-  }
-
-  int get version => 0;
-}
-
-
diff --git a/gen/dart-pkg/mojom/lib/mojo/examples/echo.mojom.dart b/gen/dart-pkg/mojom/lib/mojo/examples/echo.mojom.dart
deleted file mode 100644
index e50c356..0000000
--- a/gen/dart-pkg/mojom/lib/mojo/examples/echo.mojom.dart
+++ /dev/null
@@ -1,319 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library echo_mojom;
-
-import 'dart:async';
-
-import 'package:mojo/bindings.dart' as bindings;
-import 'package:mojo/core.dart' as core;
-
-
-class EchoEchoStringParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String value = null;
-
-  EchoEchoStringParams() : super(kVersions.last.size);
-
-  static EchoEchoStringParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static EchoEchoStringParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    EchoEchoStringParams result = new EchoEchoStringParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.value = decoder0.decodeString(8, true);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(value, 8, true);
-  }
-
-  String toString() {
-    return "EchoEchoStringParams("
-           "value: $value" ")";
-  }
-}
-
-class EchoEchoStringResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String value = null;
-
-  EchoEchoStringResponseParams() : super(kVersions.last.size);
-
-  static EchoEchoStringResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static EchoEchoStringResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    EchoEchoStringResponseParams result = new EchoEchoStringResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.value = decoder0.decodeString(8, true);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(value, 8, true);
-  }
-
-  String toString() {
-    return "EchoEchoStringResponseParams("
-           "value: $value" ")";
-  }
-}
-
-const int kEcho_echoString_name = 0;
-
-const String EchoName =
-      'mojo::examples::Echo';
-
-abstract class Echo {
-  Future<EchoEchoStringResponseParams> echoString(String value,[Function responseFactory = null]);
-
-}
-
-
-class EchoProxyImpl extends bindings.Proxy {
-  EchoProxyImpl.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
-
-  EchoProxyImpl.fromHandle(core.MojoHandle handle) :
-      super.fromHandle(handle);
-
-  EchoProxyImpl.unbound() : super.unbound();
-
-  static EchoProxyImpl newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For EchoProxyImpl"));
-    return new EchoProxyImpl.fromEndpoint(endpoint);
-  }
-
-  String get name => EchoName;
-
-  void handleResponse(bindings.ServiceMessage message) {
-    switch (message.header.type) {
-      case kEcho_echoString_name:
-        var r = EchoEchoStringResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      default:
-        throw new bindings.MojoCodecError("Unexpected message name");
-        break;
-    }
-  }
-
-  String toString() {
-    var superString = super.toString();
-    return "EchoProxyImpl($superString)";
-  }
-}
-
-
-class _EchoProxyCalls implements Echo {
-  EchoProxyImpl _proxyImpl;
-
-  _EchoProxyCalls(this._proxyImpl);
-    Future<EchoEchoStringResponseParams> echoString(String value,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new EchoEchoStringParams();
-      params.value = value;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kEcho_echoString_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-}
-
-
-class EchoProxy implements bindings.ProxyBase {
-  final bindings.Proxy impl;
-  Echo ptr;
-  final String name = EchoName;
-
-  EchoProxy(EchoProxyImpl proxyImpl) :
-      impl = proxyImpl,
-      ptr = new _EchoProxyCalls(proxyImpl);
-
-  EchoProxy.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) :
-      impl = new EchoProxyImpl.fromEndpoint(endpoint) {
-    ptr = new _EchoProxyCalls(impl);
-  }
-
-  EchoProxy.fromHandle(core.MojoHandle handle) :
-      impl = new EchoProxyImpl.fromHandle(handle) {
-    ptr = new _EchoProxyCalls(impl);
-  }
-
-  EchoProxy.unbound() :
-      impl = new EchoProxyImpl.unbound() {
-    ptr = new _EchoProxyCalls(impl);
-  }
-
-  static EchoProxy newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For EchoProxy"));
-    return new EchoProxy.fromEndpoint(endpoint);
-  }
-
-  Future close({bool immediate: false}) => impl.close(immediate: immediate);
-
-  int get version => impl.version;
-
-  Future<int> queryVersion() => impl.queryVersion();
-
-  void requireVersion(int requiredVersion) {
-    impl.requireVersion(requiredVersion);
-  }
-
-  String toString() {
-    return "EchoProxy($impl)";
-  }
-}
-
-
-class EchoStub extends bindings.Stub {
-  Echo _impl = null;
-
-  EchoStub.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint, [this._impl])
-      : super.fromEndpoint(endpoint);
-
-  EchoStub.fromHandle(core.MojoHandle handle, [this._impl])
-      : super.fromHandle(handle);
-
-  EchoStub.unbound() : super.unbound();
-
-  static EchoStub newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For EchoStub"));
-    return new EchoStub.fromEndpoint(endpoint);
-  }
-
-  static const String name = EchoName;
-
-
-  EchoEchoStringResponseParams _EchoEchoStringResponseParamsFactory(String value) {
-    var result = new EchoEchoStringResponseParams();
-    result.value = value;
-    return result;
-  }
-
-  Future<bindings.Message> handleMessage(bindings.ServiceMessage message) {
-    if (bindings.ControlMessageHandler.isControlMessage(message)) {
-      return bindings.ControlMessageHandler.handleMessage(this,
-                                                          0,
-                                                          message);
-    }
-    assert(_impl != null);
-    switch (message.header.type) {
-      case kEcho_echoString_name:
-        var params = EchoEchoStringParams.deserialize(
-            message.payload);
-        return _impl.echoString(params.value,_EchoEchoStringResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kEcho_echoString_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      default:
-        throw new bindings.MojoCodecError("Unexpected message name");
-        break;
-    }
-    return null;
-  }
-
-  Echo get impl => _impl;
-  set impl(Echo d) {
-    assert(_impl == null);
-    _impl = d;
-  }
-
-  String toString() {
-    var superString = super.toString();
-    return "EchoStub($superString)";
-  }
-
-  int get version => 0;
-}
-
-
diff --git a/gen/dart-pkg/mojom/lib/mojo/syncbase/syncbase.mojom.dart b/gen/dart-pkg/mojom/lib/mojo/syncbase/syncbase.mojom.dart
deleted file mode 100644
index c88c4c7..0000000
--- a/gen/dart-pkg/mojom/lib/mojo/syncbase/syncbase.mojom.dart
+++ /dev/null
@@ -1,7098 +0,0 @@
-// Copyright 2014 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-library syncbase_mojom;
-
-import 'dart:async';
-
-import 'package:mojo/bindings.dart' as bindings;
-import 'package:mojo/core.dart' as core;
-
-
-class Error extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String id = null;
-  int actionCode = 0;
-  String msg = null;
-
-  Error() : super(kVersions.last.size);
-
-  static Error deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static Error decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    Error result = new Error();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.id = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.actionCode = decoder0.decodeUint32(16);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.msg = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(id, 8, false);
-    
-    encoder0.encodeUint32(actionCode, 16);
-    
-    encoder0.encodeString(msg, 24, false);
-  }
-
-  String toString() {
-    return "Error("
-           "id: $id" ", "
-           "actionCode: $actionCode" ", "
-           "msg: $msg" ")";
-  }
-}
-
-class Perms extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String json = null;
-
-  Perms() : super(kVersions.last.size);
-
-  static Perms deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static Perms decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    Perms result = new Perms();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.json = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(json, 8, false);
-  }
-
-  String toString() {
-    return "Perms("
-           "json: $json" ")";
-  }
-}
-
-class BatchOptions extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String hint = null;
-  bool readOnly = false;
-
-  BatchOptions() : super(kVersions.last.size);
-
-  static BatchOptions deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static BatchOptions decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    BatchOptions result = new BatchOptions();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.hint = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.readOnly = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(hint, 8, false);
-    
-    encoder0.encodeBool(readOnly, 16, 0);
-  }
-
-  String toString() {
-    return "BatchOptions("
-           "hint: $hint" ", "
-           "readOnly: $readOnly" ")";
-  }
-}
-
-class PrefixPerms extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String prefix = null;
-  Perms perms = null;
-
-  PrefixPerms() : super(kVersions.last.size);
-
-  static PrefixPerms deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static PrefixPerms decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    PrefixPerms result = new PrefixPerms();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.prefix = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(prefix, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-  }
-
-  String toString() {
-    return "PrefixPerms("
-           "prefix: $prefix" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncGroupSpec extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(48, 0)
-  ];
-  String description = null;
-  Perms perms = null;
-  List<String> prefixes = null;
-  List<String> mountTables = null;
-  bool isPrivate = false;
-
-  SyncGroupSpec() : super(kVersions.last.size);
-
-  static SyncGroupSpec deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncGroupSpec decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncGroupSpec result = new SyncGroupSpec();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.description = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.prefixes = new List<String>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          result.prefixes[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(32, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.mountTables = new List<String>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          result.mountTables[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.isPrivate = decoder0.decodeBool(40, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(description, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    if (prefixes == null) {
-      encoder0.encodeNullPointer(24, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(prefixes.length, 24, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < prefixes.length; ++i0) {
-        
-        encoder1.encodeString(prefixes[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-    
-    if (mountTables == null) {
-      encoder0.encodeNullPointer(32, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(mountTables.length, 32, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < mountTables.length; ++i0) {
-        
-        encoder1.encodeString(mountTables[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-    
-    encoder0.encodeBool(isPrivate, 40, 0);
-  }
-
-  String toString() {
-    return "SyncGroupSpec("
-           "description: $description" ", "
-           "perms: $perms" ", "
-           "prefixes: $prefixes" ", "
-           "mountTables: $mountTables" ", "
-           "isPrivate: $isPrivate" ")";
-  }
-}
-
-class SyncGroupMemberInfo extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  int syncPriority = 0;
-
-  SyncGroupMemberInfo() : super(kVersions.last.size);
-
-  static SyncGroupMemberInfo deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncGroupMemberInfo decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncGroupMemberInfo result = new SyncGroupMemberInfo();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.syncPriority = decoder0.decodeUint8(8);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeUint8(syncPriority, 8);
-  }
-
-  String toString() {
-    return "SyncGroupMemberInfo("
-           "syncPriority: $syncPriority" ")";
-  }
-}
-
-class SyncbaseServiceGetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(8, 0)
-  ];
-
-  SyncbaseServiceGetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseServiceGetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseServiceGetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseServiceGetPermissionsParams result = new SyncbaseServiceGetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    encoder.getStructEncoderAtOffset(kVersions.last);
-  }
-
-  String toString() {
-    return "SyncbaseServiceGetPermissionsParams("")";
-  }
-}
-
-class SyncbaseServiceGetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  Error err = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseServiceGetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseServiceGetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseServiceGetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseServiceGetPermissionsResponseParams result = new SyncbaseServiceGetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseServiceGetPermissionsResponseParams("
-           "err: $err" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseServiceSetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseServiceSetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseServiceSetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseServiceSetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseServiceSetPermissionsParams result = new SyncbaseServiceSetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(perms, 8, false);
-    
-    encoder0.encodeString(version, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseServiceSetPermissionsParams("
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseServiceSetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseServiceSetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseServiceSetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseServiceSetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseServiceSetPermissionsResponseParams result = new SyncbaseServiceSetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseServiceSetPermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseAppCreateParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-
-  SyncbaseAppCreateParams() : super(kVersions.last.size);
-
-  static SyncbaseAppCreateParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppCreateParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppCreateParams result = new SyncbaseAppCreateParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppCreateParams("
-           "name: $name" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncbaseAppCreateResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseAppCreateResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppCreateResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppCreateResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppCreateResponseParams result = new SyncbaseAppCreateResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppCreateResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseAppDeleteParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseAppDeleteParams() : super(kVersions.last.size);
-
-  static SyncbaseAppDeleteParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppDeleteParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppDeleteParams result = new SyncbaseAppDeleteParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppDeleteParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseAppDeleteResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseAppDeleteResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppDeleteResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppDeleteResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppDeleteResponseParams result = new SyncbaseAppDeleteResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppDeleteResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseAppExistsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseAppExistsParams() : super(kVersions.last.size);
-
-  static SyncbaseAppExistsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppExistsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppExistsParams result = new SyncbaseAppExistsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppExistsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseAppExistsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  bool exists = false;
-
-  SyncbaseAppExistsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppExistsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppExistsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppExistsResponseParams result = new SyncbaseAppExistsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.exists = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeBool(exists, 16, 0);
-  }
-
-  String toString() {
-    return "SyncbaseAppExistsResponseParams("
-           "err: $err" ", "
-           "exists: $exists" ")";
-  }
-}
-
-class SyncbaseAppGetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseAppGetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseAppGetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppGetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppGetPermissionsParams result = new SyncbaseAppGetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppGetPermissionsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseAppGetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  Error err = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseAppGetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppGetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppGetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppGetPermissionsResponseParams result = new SyncbaseAppGetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppGetPermissionsResponseParams("
-           "err: $err" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseAppSetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseAppSetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseAppSetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppSetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppSetPermissionsParams result = new SyncbaseAppSetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppSetPermissionsParams("
-           "name: $name" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseAppSetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseAppSetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseAppSetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseAppSetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseAppSetPermissionsResponseParams result = new SyncbaseAppSetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseAppSetPermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbCreateParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-
-  SyncbaseDbCreateParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCreateParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCreateParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCreateParams result = new SyncbaseDbCreateParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCreateParams("
-           "name: $name" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncbaseDbCreateResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbCreateResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCreateResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCreateResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCreateResponseParams result = new SyncbaseDbCreateResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCreateResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbDeleteParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbDeleteParams() : super(kVersions.last.size);
-
-  static SyncbaseDbDeleteParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbDeleteParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbDeleteParams result = new SyncbaseDbDeleteParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbDeleteParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbDeleteResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbDeleteResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbDeleteResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbDeleteResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbDeleteResponseParams result = new SyncbaseDbDeleteResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbDeleteResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbExistsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbExistsParams() : super(kVersions.last.size);
-
-  static SyncbaseDbExistsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbExistsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbExistsParams result = new SyncbaseDbExistsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbExistsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbExistsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  bool exists = false;
-
-  SyncbaseDbExistsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbExistsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbExistsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbExistsResponseParams result = new SyncbaseDbExistsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.exists = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeBool(exists, 16, 0);
-  }
-
-  String toString() {
-    return "SyncbaseDbExistsResponseParams("
-           "err: $err" ", "
-           "exists: $exists" ")";
-  }
-}
-
-class SyncbaseDbExecParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String query = null;
-
-  SyncbaseDbExecParams() : super(kVersions.last.size);
-
-  static SyncbaseDbExecParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbExecParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbExecParams result = new SyncbaseDbExecParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.query = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(query, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbExecParams("
-           "query: $query" ")";
-  }
-}
-
-class SyncbaseDbExecResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbExecResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbExecResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbExecResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbExecResponseParams result = new SyncbaseDbExecResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbExecResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbBeginBatchParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  BatchOptions bo = null;
-
-  SyncbaseDbBeginBatchParams() : super(kVersions.last.size);
-
-  static SyncbaseDbBeginBatchParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbBeginBatchParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbBeginBatchParams result = new SyncbaseDbBeginBatchParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, true);
-      result.bo = BatchOptions.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(bo, 16, true);
-  }
-
-  String toString() {
-    return "SyncbaseDbBeginBatchParams("
-           "name: $name" ", "
-           "bo: $bo" ")";
-  }
-}
-
-class SyncbaseDbBeginBatchResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  String batchDn = null;
-
-  SyncbaseDbBeginBatchResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbBeginBatchResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbBeginBatchResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbBeginBatchResponseParams result = new SyncbaseDbBeginBatchResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.batchDn = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeString(batchDn, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbBeginBatchResponseParams("
-           "err: $err" ", "
-           "batchDn: $batchDn" ")";
-  }
-}
-
-class SyncbaseDbCommitParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbCommitParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCommitParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCommitParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCommitParams result = new SyncbaseDbCommitParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCommitParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbCommitResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbCommitResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCommitResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCommitResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCommitResponseParams result = new SyncbaseDbCommitResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCommitResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbAbortParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbAbortParams() : super(kVersions.last.size);
-
-  static SyncbaseDbAbortParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbAbortParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbAbortParams result = new SyncbaseDbAbortParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbAbortParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbAbortResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbAbortResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbAbortResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbAbortResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbAbortResponseParams result = new SyncbaseDbAbortResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbAbortResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbGetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbGetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetPermissionsParams result = new SyncbaseDbGetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetPermissionsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbGetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  Error err = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseDbGetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetPermissionsResponseParams result = new SyncbaseDbGetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetPermissionsResponseParams("
-           "err: $err" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseDbSetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-  String version = null;
-
-  SyncbaseDbSetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseDbSetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbSetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbSetPermissionsParams result = new SyncbaseDbSetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbSetPermissionsParams("
-           "name: $name" ", "
-           "perms: $perms" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseDbSetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbSetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbSetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbSetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbSetPermissionsResponseParams result = new SyncbaseDbSetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbSetPermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupNamesParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseDbGetSyncGroupNamesParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupNamesParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupNamesParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupNamesParams result = new SyncbaseDbGetSyncGroupNamesParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupNamesParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupNamesResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  List<String> names = null;
-
-  SyncbaseDbGetSyncGroupNamesResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupNamesResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupNamesResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupNamesResponseParams result = new SyncbaseDbGetSyncGroupNamesResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.names = new List<String>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          result.names[i1] = decoder1.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    if (names == null) {
-      encoder0.encodeNullPointer(16, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(names.length, 16, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < names.length; ++i0) {
-        
-        encoder1.encodeString(names[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupNamesResponseParams("
-           "err: $err" ", "
-           "names: $names" ")";
-  }
-}
-
-class SyncbaseDbCreateSyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(40, 0)
-  ];
-  String name = null;
-  String sgName = null;
-  SyncGroupSpec spec = null;
-  SyncGroupMemberInfo myInfo = null;
-
-  SyncbaseDbCreateSyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCreateSyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCreateSyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCreateSyncGroupParams result = new SyncbaseDbCreateSyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      result.spec = SyncGroupSpec.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(32, false);
-      result.myInfo = SyncGroupMemberInfo.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-    
-    encoder0.encodeStruct(spec, 24, false);
-    
-    encoder0.encodeStruct(myInfo, 32, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCreateSyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ", "
-           "spec: $spec" ", "
-           "myInfo: $myInfo" ")";
-  }
-}
-
-class SyncbaseDbCreateSyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbCreateSyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbCreateSyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbCreateSyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbCreateSyncGroupResponseParams result = new SyncbaseDbCreateSyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbCreateSyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbJoinSyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  String sgName = null;
-  SyncGroupMemberInfo myInfo = null;
-
-  SyncbaseDbJoinSyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbJoinSyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbJoinSyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbJoinSyncGroupParams result = new SyncbaseDbJoinSyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      result.myInfo = SyncGroupMemberInfo.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-    
-    encoder0.encodeStruct(myInfo, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbJoinSyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ", "
-           "myInfo: $myInfo" ")";
-  }
-}
-
-class SyncbaseDbJoinSyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbJoinSyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbJoinSyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbJoinSyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbJoinSyncGroupResponseParams result = new SyncbaseDbJoinSyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbJoinSyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbLeaveSyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String sgName = null;
-
-  SyncbaseDbLeaveSyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbLeaveSyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbLeaveSyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbLeaveSyncGroupParams result = new SyncbaseDbLeaveSyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbLeaveSyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ")";
-  }
-}
-
-class SyncbaseDbLeaveSyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbLeaveSyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbLeaveSyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbLeaveSyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbLeaveSyncGroupResponseParams result = new SyncbaseDbLeaveSyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbLeaveSyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbDestroySyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String sgName = null;
-
-  SyncbaseDbDestroySyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbDestroySyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbDestroySyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbDestroySyncGroupParams result = new SyncbaseDbDestroySyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbDestroySyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ")";
-  }
-}
-
-class SyncbaseDbDestroySyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbDestroySyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbDestroySyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbDestroySyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbDestroySyncGroupResponseParams result = new SyncbaseDbDestroySyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbDestroySyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbEjectFromSyncGroupParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  String sgName = null;
-  String member = null;
-
-  SyncbaseDbEjectFromSyncGroupParams() : super(kVersions.last.size);
-
-  static SyncbaseDbEjectFromSyncGroupParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbEjectFromSyncGroupParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbEjectFromSyncGroupParams result = new SyncbaseDbEjectFromSyncGroupParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.member = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-    
-    encoder0.encodeString(member, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbEjectFromSyncGroupParams("
-           "name: $name" ", "
-           "sgName: $sgName" ", "
-           "member: $member" ")";
-  }
-}
-
-class SyncbaseDbEjectFromSyncGroupResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbEjectFromSyncGroupResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbEjectFromSyncGroupResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbEjectFromSyncGroupResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbEjectFromSyncGroupResponseParams result = new SyncbaseDbEjectFromSyncGroupResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbEjectFromSyncGroupResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupSpecParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String sgName = null;
-
-  SyncbaseDbGetSyncGroupSpecParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupSpecParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupSpecParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupSpecParams result = new SyncbaseDbGetSyncGroupSpecParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupSpecParams("
-           "name: $name" ", "
-           "sgName: $sgName" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupSpecResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  Error err = null;
-  SyncGroupSpec spec = null;
-  String version = null;
-
-  SyncbaseDbGetSyncGroupSpecResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupSpecResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupSpecResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupSpecResponseParams result = new SyncbaseDbGetSyncGroupSpecResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.spec = SyncGroupSpec.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(24, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeStruct(spec, 16, false);
-    
-    encoder0.encodeString(version, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupSpecResponseParams("
-           "err: $err" ", "
-           "spec: $spec" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseDbSetSyncGroupSpecParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(40, 0)
-  ];
-  String name = null;
-  String sgName = null;
-  SyncGroupSpec spec = null;
-  String version = null;
-
-  SyncbaseDbSetSyncGroupSpecParams() : super(kVersions.last.size);
-
-  static SyncbaseDbSetSyncGroupSpecParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbSetSyncGroupSpecParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbSetSyncGroupSpecParams result = new SyncbaseDbSetSyncGroupSpecParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      result.spec = SyncGroupSpec.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.version = decoder0.decodeString(32, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-    
-    encoder0.encodeStruct(spec, 24, false);
-    
-    encoder0.encodeString(version, 32, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbSetSyncGroupSpecParams("
-           "name: $name" ", "
-           "sgName: $sgName" ", "
-           "spec: $spec" ", "
-           "version: $version" ")";
-  }
-}
-
-class SyncbaseDbSetSyncGroupSpecResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseDbSetSyncGroupSpecResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbSetSyncGroupSpecResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbSetSyncGroupSpecResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbSetSyncGroupSpecResponseParams result = new SyncbaseDbSetSyncGroupSpecResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbSetSyncGroupSpecResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupMembersParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String sgName = null;
-
-  SyncbaseDbGetSyncGroupMembersParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupMembersParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupMembersParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupMembersParams result = new SyncbaseDbGetSyncGroupMembersParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.sgName = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(sgName, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupMembersParams("
-           "name: $name" ", "
-           "sgName: $sgName" ")";
-  }
-}
-
-class SyncbaseDbGetSyncGroupMembersResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  Map<String, SyncGroupMemberInfo> infos = null;
-
-  SyncbaseDbGetSyncGroupMembersResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseDbGetSyncGroupMembersResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseDbGetSyncGroupMembersResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseDbGetSyncGroupMembersResponseParams result = new SyncbaseDbGetSyncGroupMembersResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      {
-        decoder1.decodeDataHeaderForMap();
-        List<String> keys0;
-        List<SyncGroupMemberInfo> values0;
-        {
-          
-          var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize, false);
-          {
-            var si2 = decoder2.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-            keys0 = new List<String>(si2.numElements);
-            for (int i2 = 0; i2 < si2.numElements; ++i2) {
-              
-              keys0[i2] = decoder2.decodeString(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i2, false);
-            }
-          }
-        }
-        {
-          
-          var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize, false);
-          {
-            var si2 = decoder2.decodeDataHeaderForPointerArray(keys0.length);
-            values0 = new List<SyncGroupMemberInfo>(si2.numElements);
-            for (int i2 = 0; i2 < si2.numElements; ++i2) {
-              
-              var decoder3 = decoder2.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i2, false);
-              values0[i2] = SyncGroupMemberInfo.decode(decoder3);
-            }
-          }
-        }
-        result.infos = new Map<String, SyncGroupMemberInfo>.fromIterables(
-            keys0, values0);
-      }
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    if (infos == null) {
-      encoder0.encodeNullPointer(16, false);
-    } else {
-      var encoder1 = encoder0.encoderForMap(16);
-      int size0 = infos.length;
-      var keys0 = infos.keys.toList();
-      var values0 = infos.values.toList();
-      
-      {
-        var encoder2 = encoder1.encodePointerArray(keys0.length, bindings.ArrayDataHeader.kHeaderSize, bindings.kUnspecifiedArrayLength);
-        for (int i1 = 0; i1 < keys0.length; ++i1) {
-          
-          encoder2.encodeString(keys0[i1], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-      
-      {
-        var encoder2 = encoder1.encodePointerArray(values0.length, bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize, bindings.kUnspecifiedArrayLength);
-        for (int i1 = 0; i1 < values0.length; ++i1) {
-          
-          encoder2.encodeStruct(values0[i1], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-        }
-      }
-    }
-  }
-
-  String toString() {
-    return "SyncbaseDbGetSyncGroupMembersResponseParams("
-           "err: $err" ", "
-           "infos: $infos" ")";
-  }
-}
-
-class SyncbaseTableCreateParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  Perms perms = null;
-
-  SyncbaseTableCreateParams() : super(kVersions.last.size);
-
-  static SyncbaseTableCreateParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableCreateParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableCreateParams result = new SyncbaseTableCreateParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeStruct(perms, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableCreateParams("
-           "name: $name" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncbaseTableCreateResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableCreateResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableCreateResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableCreateResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableCreateResponseParams result = new SyncbaseTableCreateResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableCreateResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableDeleteParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseTableDeleteParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeleteParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeleteParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeleteParams result = new SyncbaseTableDeleteParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeleteParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseTableDeleteResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableDeleteResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeleteResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeleteResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeleteResponseParams result = new SyncbaseTableDeleteResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeleteResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableExistsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseTableExistsParams() : super(kVersions.last.size);
-
-  static SyncbaseTableExistsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableExistsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableExistsParams result = new SyncbaseTableExistsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableExistsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseTableExistsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  bool exists = false;
-
-  SyncbaseTableExistsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableExistsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableExistsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableExistsResponseParams result = new SyncbaseTableExistsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.exists = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeBool(exists, 16, 0);
-  }
-
-  String toString() {
-    return "SyncbaseTableExistsResponseParams("
-           "err: $err" ", "
-           "exists: $exists" ")";
-  }
-}
-
-class SyncbaseTableDeleteRowRangeParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  List<int> start = null;
-  List<int> limit = null;
-
-  SyncbaseTableDeleteRowRangeParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeleteRowRangeParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeleteRowRangeParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeleteRowRangeParams result = new SyncbaseTableDeleteRowRangeParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.start = decoder0.decodeUint8Array(16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.limit = decoder0.decodeUint8Array(24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeUint8Array(start, 16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    
-    encoder0.encodeUint8Array(limit, 24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeleteRowRangeParams("
-           "name: $name" ", "
-           "start: $start" ", "
-           "limit: $limit" ")";
-  }
-}
-
-class SyncbaseTableDeleteRowRangeResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableDeleteRowRangeResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeleteRowRangeResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeleteRowRangeResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeleteRowRangeResponseParams result = new SyncbaseTableDeleteRowRangeResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeleteRowRangeResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableScanParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  List<int> start = null;
-  List<int> limit = null;
-
-  SyncbaseTableScanParams() : super(kVersions.last.size);
-
-  static SyncbaseTableScanParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableScanParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableScanParams result = new SyncbaseTableScanParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.start = decoder0.decodeUint8Array(16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.limit = decoder0.decodeUint8Array(24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeUint8Array(start, 16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    
-    encoder0.encodeUint8Array(limit, 24, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-  }
-
-  String toString() {
-    return "SyncbaseTableScanParams("
-           "name: $name" ", "
-           "start: $start" ", "
-           "limit: $limit" ")";
-  }
-}
-
-class SyncbaseTableScanResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableScanResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableScanResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableScanResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableScanResponseParams result = new SyncbaseTableScanResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableScanResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableGetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String key = null;
-
-  SyncbaseTableGetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseTableGetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableGetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableGetPermissionsParams result = new SyncbaseTableGetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.key = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(key, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableGetPermissionsParams("
-           "name: $name" ", "
-           "key: $key" ")";
-  }
-}
-
-class SyncbaseTableGetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  List<PrefixPerms> permsArr = null;
-
-  SyncbaseTableGetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableGetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableGetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableGetPermissionsResponseParams result = new SyncbaseTableGetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(16, false);
-      {
-        var si1 = decoder1.decodeDataHeaderForPointerArray(bindings.kUnspecifiedArrayLength);
-        result.permsArr = new List<PrefixPerms>(si1.numElements);
-        for (int i1 = 0; i1 < si1.numElements; ++i1) {
-          
-          var decoder2 = decoder1.decodePointer(bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i1, false);
-          result.permsArr[i1] = PrefixPerms.decode(decoder2);
-        }
-      }
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    if (permsArr == null) {
-      encoder0.encodeNullPointer(16, false);
-    } else {
-      var encoder1 = encoder0.encodePointerArray(permsArr.length, 16, bindings.kUnspecifiedArrayLength);
-      for (int i0 = 0; i0 < permsArr.length; ++i0) {
-        
-        encoder1.encodeStruct(permsArr[i0], bindings.ArrayDataHeader.kHeaderSize + bindings.kPointerSize * i0, false);
-      }
-    }
-  }
-
-  String toString() {
-    return "SyncbaseTableGetPermissionsResponseParams("
-           "err: $err" ", "
-           "permsArr: $permsArr" ")";
-  }
-}
-
-class SyncbaseTableSetPermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(32, 0)
-  ];
-  String name = null;
-  String prefix = null;
-  Perms perms = null;
-
-  SyncbaseTableSetPermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseTableSetPermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableSetPermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableSetPermissionsParams result = new SyncbaseTableSetPermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.prefix = decoder0.decodeString(16, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(24, false);
-      result.perms = Perms.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(prefix, 16, false);
-    
-    encoder0.encodeStruct(perms, 24, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableSetPermissionsParams("
-           "name: $name" ", "
-           "prefix: $prefix" ", "
-           "perms: $perms" ")";
-  }
-}
-
-class SyncbaseTableSetPermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableSetPermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableSetPermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableSetPermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableSetPermissionsResponseParams result = new SyncbaseTableSetPermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableSetPermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseTableDeletePermissionsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  String prefix = null;
-
-  SyncbaseTableDeletePermissionsParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeletePermissionsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeletePermissionsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeletePermissionsParams result = new SyncbaseTableDeletePermissionsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.prefix = decoder0.decodeString(16, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeString(prefix, 16, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeletePermissionsParams("
-           "name: $name" ", "
-           "prefix: $prefix" ")";
-  }
-}
-
-class SyncbaseTableDeletePermissionsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseTableDeletePermissionsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseTableDeletePermissionsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseTableDeletePermissionsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseTableDeletePermissionsResponseParams result = new SyncbaseTableDeletePermissionsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseTableDeletePermissionsResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseRowExistsParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseRowExistsParams() : super(kVersions.last.size);
-
-  static SyncbaseRowExistsParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowExistsParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowExistsParams result = new SyncbaseRowExistsParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowExistsParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseRowExistsResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  bool exists = false;
-
-  SyncbaseRowExistsResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseRowExistsResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowExistsResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowExistsResponseParams result = new SyncbaseRowExistsResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.exists = decoder0.decodeBool(16, 0);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeBool(exists, 16, 0);
-  }
-
-  String toString() {
-    return "SyncbaseRowExistsResponseParams("
-           "err: $err" ", "
-           "exists: $exists" ")";
-  }
-}
-
-class SyncbaseRowGetParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseRowGetParams() : super(kVersions.last.size);
-
-  static SyncbaseRowGetParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowGetParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowGetParams result = new SyncbaseRowGetParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowGetParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseRowGetResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  Error err = null;
-  List<int> value = null;
-
-  SyncbaseRowGetResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseRowGetResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowGetResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowGetResponseParams result = new SyncbaseRowGetResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.value = decoder0.decodeUint8Array(16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-    
-    encoder0.encodeUint8Array(value, 16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-  }
-
-  String toString() {
-    return "SyncbaseRowGetResponseParams("
-           "err: $err" ", "
-           "value: $value" ")";
-  }
-}
-
-class SyncbaseRowPutParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(24, 0)
-  ];
-  String name = null;
-  List<int> value = null;
-
-  SyncbaseRowPutParams() : super(kVersions.last.size);
-
-  static SyncbaseRowPutParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowPutParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowPutParams result = new SyncbaseRowPutParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.value = decoder0.decodeUint8Array(16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-    
-    encoder0.encodeUint8Array(value, 16, bindings.kNothingNullable, bindings.kUnspecifiedArrayLength);
-  }
-
-  String toString() {
-    return "SyncbaseRowPutParams("
-           "name: $name" ", "
-           "value: $value" ")";
-  }
-}
-
-class SyncbaseRowPutResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseRowPutResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseRowPutResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowPutResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowPutResponseParams result = new SyncbaseRowPutResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowPutResponseParams("
-           "err: $err" ")";
-  }
-}
-
-class SyncbaseRowDeleteParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  String name = null;
-
-  SyncbaseRowDeleteParams() : super(kVersions.last.size);
-
-  static SyncbaseRowDeleteParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowDeleteParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowDeleteParams result = new SyncbaseRowDeleteParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      result.name = decoder0.decodeString(8, false);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeString(name, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowDeleteParams("
-           "name: $name" ")";
-  }
-}
-
-class SyncbaseRowDeleteResponseParams extends bindings.Struct {
-  static const List<bindings.StructDataHeader> kVersions = const [
-    const bindings.StructDataHeader(16, 0)
-  ];
-  Error err = null;
-
-  SyncbaseRowDeleteResponseParams() : super(kVersions.last.size);
-
-  static SyncbaseRowDeleteResponseParams deserialize(bindings.Message message) {
-    var decoder = new bindings.Decoder(message);
-    var result = decode(decoder);
-    decoder.excessHandles.forEach((h) => h.close());
-    return result;
-  }
-
-  static SyncbaseRowDeleteResponseParams decode(bindings.Decoder decoder0) {
-    if (decoder0 == null) {
-      return null;
-    }
-    SyncbaseRowDeleteResponseParams result = new SyncbaseRowDeleteResponseParams();
-
-    var mainDataHeader = decoder0.decodeStructDataHeader();
-    if (mainDataHeader.version <= kVersions.last.version) {
-      // Scan in reverse order to optimize for more recent versions.
-      for (int i = kVersions.length - 1; i >= 0; --i) {
-        if (mainDataHeader.version >= kVersions[i].version) {
-          if (mainDataHeader.size == kVersions[i].size) {
-            // Found a match.
-            break;
-          }
-          throw new bindings.MojoCodecError(
-              'Header size doesn\'t correspond to known version size.');
-        }
-      }
-    } else if (mainDataHeader.size < kVersions.last.size) {
-      throw new bindings.MojoCodecError(
-        'Message newer than the last known version cannot be shorter than '
-        'required by the last known version.');
-    }
-    if (mainDataHeader.version >= 0) {
-      
-      var decoder1 = decoder0.decodePointer(8, false);
-      result.err = Error.decode(decoder1);
-    }
-    return result;
-  }
-
-  void encode(bindings.Encoder encoder) {
-    var encoder0 = encoder.getStructEncoderAtOffset(kVersions.last);
-    
-    encoder0.encodeStruct(err, 8, false);
-  }
-
-  String toString() {
-    return "SyncbaseRowDeleteResponseParams("
-           "err: $err" ")";
-  }
-}
-
-const int kSyncbase_serviceGetPermissions_name = 0;
-const int kSyncbase_serviceSetPermissions_name = 1;
-const int kSyncbase_appCreate_name = 2;
-const int kSyncbase_appDelete_name = 3;
-const int kSyncbase_appExists_name = 4;
-const int kSyncbase_appGetPermissions_name = 5;
-const int kSyncbase_appSetPermissions_name = 6;
-const int kSyncbase_dbCreate_name = 7;
-const int kSyncbase_dbDelete_name = 8;
-const int kSyncbase_dbExists_name = 9;
-const int kSyncbase_dbExec_name = 10;
-const int kSyncbase_dbBeginBatch_name = 11;
-const int kSyncbase_dbCommit_name = 12;
-const int kSyncbase_dbAbort_name = 13;
-const int kSyncbase_dbGetPermissions_name = 14;
-const int kSyncbase_dbSetPermissions_name = 15;
-const int kSyncbase_dbGetSyncGroupNames_name = 16;
-const int kSyncbase_dbCreateSyncGroup_name = 17;
-const int kSyncbase_dbJoinSyncGroup_name = 18;
-const int kSyncbase_dbLeaveSyncGroup_name = 19;
-const int kSyncbase_dbDestroySyncGroup_name = 20;
-const int kSyncbase_dbEjectFromSyncGroup_name = 21;
-const int kSyncbase_dbGetSyncGroupSpec_name = 22;
-const int kSyncbase_dbSetSyncGroupSpec_name = 23;
-const int kSyncbase_dbGetSyncGroupMembers_name = 24;
-const int kSyncbase_tableCreate_name = 25;
-const int kSyncbase_tableDelete_name = 26;
-const int kSyncbase_tableExists_name = 27;
-const int kSyncbase_tableDeleteRowRange_name = 28;
-const int kSyncbase_tableScan_name = 29;
-const int kSyncbase_tableGetPermissions_name = 30;
-const int kSyncbase_tableSetPermissions_name = 31;
-const int kSyncbase_tableDeletePermissions_name = 32;
-const int kSyncbase_rowExists_name = 33;
-const int kSyncbase_rowGet_name = 34;
-const int kSyncbase_rowPut_name = 35;
-const int kSyncbase_rowDelete_name = 36;
-
-const String SyncbaseName =
-      'mojo::syncbase::Syncbase';
-
-abstract class Syncbase {
-  Future<SyncbaseServiceGetPermissionsResponseParams> serviceGetPermissions([Function responseFactory = null]);
-  Future<SyncbaseServiceSetPermissionsResponseParams> serviceSetPermissions(Perms perms,String version,[Function responseFactory = null]);
-  Future<SyncbaseAppCreateResponseParams> appCreate(String name,Perms perms,[Function responseFactory = null]);
-  Future<SyncbaseAppDeleteResponseParams> appDelete(String name,[Function responseFactory = null]);
-  Future<SyncbaseAppExistsResponseParams> appExists(String name,[Function responseFactory = null]);
-  Future<SyncbaseAppGetPermissionsResponseParams> appGetPermissions(String name,[Function responseFactory = null]);
-  Future<SyncbaseAppSetPermissionsResponseParams> appSetPermissions(String name,Perms perms,String version,[Function responseFactory = null]);
-  Future<SyncbaseDbCreateResponseParams> dbCreate(String name,Perms perms,[Function responseFactory = null]);
-  Future<SyncbaseDbDeleteResponseParams> dbDelete(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbExistsResponseParams> dbExists(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbExecResponseParams> dbExec(String query,[Function responseFactory = null]);
-  Future<SyncbaseDbBeginBatchResponseParams> dbBeginBatch(String name,BatchOptions bo,[Function responseFactory = null]);
-  Future<SyncbaseDbCommitResponseParams> dbCommit(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbAbortResponseParams> dbAbort(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbGetPermissionsResponseParams> dbGetPermissions(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbSetPermissionsResponseParams> dbSetPermissions(String name,Perms perms,String version,[Function responseFactory = null]);
-  Future<SyncbaseDbGetSyncGroupNamesResponseParams> dbGetSyncGroupNames(String name,[Function responseFactory = null]);
-  Future<SyncbaseDbCreateSyncGroupResponseParams> dbCreateSyncGroup(String name,String sgName,SyncGroupSpec spec,SyncGroupMemberInfo myInfo,[Function responseFactory = null]);
-  Future<SyncbaseDbJoinSyncGroupResponseParams> dbJoinSyncGroup(String name,String sgName,SyncGroupMemberInfo myInfo,[Function responseFactory = null]);
-  Future<SyncbaseDbLeaveSyncGroupResponseParams> dbLeaveSyncGroup(String name,String sgName,[Function responseFactory = null]);
-  Future<SyncbaseDbDestroySyncGroupResponseParams> dbDestroySyncGroup(String name,String sgName,[Function responseFactory = null]);
-  Future<SyncbaseDbEjectFromSyncGroupResponseParams> dbEjectFromSyncGroup(String name,String sgName,String member,[Function responseFactory = null]);
-  Future<SyncbaseDbGetSyncGroupSpecResponseParams> dbGetSyncGroupSpec(String name,String sgName,[Function responseFactory = null]);
-  Future<SyncbaseDbSetSyncGroupSpecResponseParams> dbSetSyncGroupSpec(String name,String sgName,SyncGroupSpec spec,String version,[Function responseFactory = null]);
-  Future<SyncbaseDbGetSyncGroupMembersResponseParams> dbGetSyncGroupMembers(String name,String sgName,[Function responseFactory = null]);
-  Future<SyncbaseTableCreateResponseParams> tableCreate(String name,Perms perms,[Function responseFactory = null]);
-  Future<SyncbaseTableDeleteResponseParams> tableDelete(String name,[Function responseFactory = null]);
-  Future<SyncbaseTableExistsResponseParams> tableExists(String name,[Function responseFactory = null]);
-  Future<SyncbaseTableDeleteRowRangeResponseParams> tableDeleteRowRange(String name,List<int> start,List<int> limit,[Function responseFactory = null]);
-  Future<SyncbaseTableScanResponseParams> tableScan(String name,List<int> start,List<int> limit,[Function responseFactory = null]);
-  Future<SyncbaseTableGetPermissionsResponseParams> tableGetPermissions(String name,String key,[Function responseFactory = null]);
-  Future<SyncbaseTableSetPermissionsResponseParams> tableSetPermissions(String name,String prefix,Perms perms,[Function responseFactory = null]);
-  Future<SyncbaseTableDeletePermissionsResponseParams> tableDeletePermissions(String name,String prefix,[Function responseFactory = null]);
-  Future<SyncbaseRowExistsResponseParams> rowExists(String name,[Function responseFactory = null]);
-  Future<SyncbaseRowGetResponseParams> rowGet(String name,[Function responseFactory = null]);
-  Future<SyncbaseRowPutResponseParams> rowPut(String name,List<int> value,[Function responseFactory = null]);
-  Future<SyncbaseRowDeleteResponseParams> rowDelete(String name,[Function responseFactory = null]);
-
-}
-
-
-class SyncbaseProxyImpl extends bindings.Proxy {
-  SyncbaseProxyImpl.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) : super.fromEndpoint(endpoint);
-
-  SyncbaseProxyImpl.fromHandle(core.MojoHandle handle) :
-      super.fromHandle(handle);
-
-  SyncbaseProxyImpl.unbound() : super.unbound();
-
-  static SyncbaseProxyImpl newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For SyncbaseProxyImpl"));
-    return new SyncbaseProxyImpl.fromEndpoint(endpoint);
-  }
-
-  String get name => SyncbaseName;
-
-  void handleResponse(bindings.ServiceMessage message) {
-    switch (message.header.type) {
-      case kSyncbase_serviceGetPermissions_name:
-        var r = SyncbaseServiceGetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_serviceSetPermissions_name:
-        var r = SyncbaseServiceSetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appCreate_name:
-        var r = SyncbaseAppCreateResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appDelete_name:
-        var r = SyncbaseAppDeleteResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appExists_name:
-        var r = SyncbaseAppExistsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appGetPermissions_name:
-        var r = SyncbaseAppGetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_appSetPermissions_name:
-        var r = SyncbaseAppSetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbCreate_name:
-        var r = SyncbaseDbCreateResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbDelete_name:
-        var r = SyncbaseDbDeleteResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbExists_name:
-        var r = SyncbaseDbExistsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbExec_name:
-        var r = SyncbaseDbExecResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbBeginBatch_name:
-        var r = SyncbaseDbBeginBatchResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbCommit_name:
-        var r = SyncbaseDbCommitResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbAbort_name:
-        var r = SyncbaseDbAbortResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbGetPermissions_name:
-        var r = SyncbaseDbGetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbSetPermissions_name:
-        var r = SyncbaseDbSetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbGetSyncGroupNames_name:
-        var r = SyncbaseDbGetSyncGroupNamesResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbCreateSyncGroup_name:
-        var r = SyncbaseDbCreateSyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbJoinSyncGroup_name:
-        var r = SyncbaseDbJoinSyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbLeaveSyncGroup_name:
-        var r = SyncbaseDbLeaveSyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbDestroySyncGroup_name:
-        var r = SyncbaseDbDestroySyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbEjectFromSyncGroup_name:
-        var r = SyncbaseDbEjectFromSyncGroupResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbGetSyncGroupSpec_name:
-        var r = SyncbaseDbGetSyncGroupSpecResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbSetSyncGroupSpec_name:
-        var r = SyncbaseDbSetSyncGroupSpecResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_dbGetSyncGroupMembers_name:
-        var r = SyncbaseDbGetSyncGroupMembersResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableCreate_name:
-        var r = SyncbaseTableCreateResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableDelete_name:
-        var r = SyncbaseTableDeleteResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableExists_name:
-        var r = SyncbaseTableExistsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableDeleteRowRange_name:
-        var r = SyncbaseTableDeleteRowRangeResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableScan_name:
-        var r = SyncbaseTableScanResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableGetPermissions_name:
-        var r = SyncbaseTableGetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableSetPermissions_name:
-        var r = SyncbaseTableSetPermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_tableDeletePermissions_name:
-        var r = SyncbaseTableDeletePermissionsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_rowExists_name:
-        var r = SyncbaseRowExistsResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_rowGet_name:
-        var r = SyncbaseRowGetResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_rowPut_name:
-        var r = SyncbaseRowPutResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      case kSyncbase_rowDelete_name:
-        var r = SyncbaseRowDeleteResponseParams.deserialize(
-            message.payload);
-        if (!message.header.hasRequestId) {
-          throw 'Expected a message with a valid request Id.';
-        }
-        Completer c = completerMap[message.header.requestId];
-        if (c == null) {
-          throw 'Message had unknown request Id: ${message.header.requestId}';
-        }
-        completerMap.remove(message.header.requestId);
-        assert(!c.isCompleted);
-        c.complete(r);
-        break;
-      default:
-        throw new bindings.MojoCodecError("Unexpected message name");
-        break;
-    }
-  }
-
-  String toString() {
-    var superString = super.toString();
-    return "SyncbaseProxyImpl($superString)";
-  }
-}
-
-
-class _SyncbaseProxyCalls implements Syncbase {
-  SyncbaseProxyImpl _proxyImpl;
-
-  _SyncbaseProxyCalls(this._proxyImpl);
-    Future<SyncbaseServiceGetPermissionsResponseParams> serviceGetPermissions([Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseServiceGetPermissionsParams();
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_serviceGetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseServiceSetPermissionsResponseParams> serviceSetPermissions(Perms perms,String version,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseServiceSetPermissionsParams();
-      params.perms = perms;
-      params.version = version;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_serviceSetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppCreateResponseParams> appCreate(String name,Perms perms,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppCreateParams();
-      params.name = name;
-      params.perms = perms;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appCreate_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppDeleteResponseParams> appDelete(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppDeleteParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appDelete_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppExistsResponseParams> appExists(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppExistsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appExists_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppGetPermissionsResponseParams> appGetPermissions(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppGetPermissionsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appGetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseAppSetPermissionsResponseParams> appSetPermissions(String name,Perms perms,String version,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseAppSetPermissionsParams();
-      params.name = name;
-      params.perms = perms;
-      params.version = version;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_appSetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbCreateResponseParams> dbCreate(String name,Perms perms,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbCreateParams();
-      params.name = name;
-      params.perms = perms;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbCreate_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbDeleteResponseParams> dbDelete(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbDeleteParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbDelete_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbExistsResponseParams> dbExists(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbExistsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbExists_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbExecResponseParams> dbExec(String query,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbExecParams();
-      params.query = query;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbExec_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbBeginBatchResponseParams> dbBeginBatch(String name,BatchOptions bo,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbBeginBatchParams();
-      params.name = name;
-      params.bo = bo;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbBeginBatch_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbCommitResponseParams> dbCommit(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbCommitParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbCommit_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbAbortResponseParams> dbAbort(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbAbortParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbAbort_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbGetPermissionsResponseParams> dbGetPermissions(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbGetPermissionsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbGetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbSetPermissionsResponseParams> dbSetPermissions(String name,Perms perms,String version,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbSetPermissionsParams();
-      params.name = name;
-      params.perms = perms;
-      params.version = version;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbSetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbGetSyncGroupNamesResponseParams> dbGetSyncGroupNames(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbGetSyncGroupNamesParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbGetSyncGroupNames_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbCreateSyncGroupResponseParams> dbCreateSyncGroup(String name,String sgName,SyncGroupSpec spec,SyncGroupMemberInfo myInfo,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbCreateSyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      params.spec = spec;
-      params.myInfo = myInfo;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbCreateSyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbJoinSyncGroupResponseParams> dbJoinSyncGroup(String name,String sgName,SyncGroupMemberInfo myInfo,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbJoinSyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      params.myInfo = myInfo;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbJoinSyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbLeaveSyncGroupResponseParams> dbLeaveSyncGroup(String name,String sgName,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbLeaveSyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbLeaveSyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbDestroySyncGroupResponseParams> dbDestroySyncGroup(String name,String sgName,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbDestroySyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbDestroySyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbEjectFromSyncGroupResponseParams> dbEjectFromSyncGroup(String name,String sgName,String member,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbEjectFromSyncGroupParams();
-      params.name = name;
-      params.sgName = sgName;
-      params.member = member;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbEjectFromSyncGroup_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbGetSyncGroupSpecResponseParams> dbGetSyncGroupSpec(String name,String sgName,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbGetSyncGroupSpecParams();
-      params.name = name;
-      params.sgName = sgName;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbGetSyncGroupSpec_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbSetSyncGroupSpecResponseParams> dbSetSyncGroupSpec(String name,String sgName,SyncGroupSpec spec,String version,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbSetSyncGroupSpecParams();
-      params.name = name;
-      params.sgName = sgName;
-      params.spec = spec;
-      params.version = version;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbSetSyncGroupSpec_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseDbGetSyncGroupMembersResponseParams> dbGetSyncGroupMembers(String name,String sgName,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseDbGetSyncGroupMembersParams();
-      params.name = name;
-      params.sgName = sgName;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_dbGetSyncGroupMembers_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableCreateResponseParams> tableCreate(String name,Perms perms,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableCreateParams();
-      params.name = name;
-      params.perms = perms;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableCreate_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableDeleteResponseParams> tableDelete(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableDeleteParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableDelete_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableExistsResponseParams> tableExists(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableExistsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableExists_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableDeleteRowRangeResponseParams> tableDeleteRowRange(String name,List<int> start,List<int> limit,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableDeleteRowRangeParams();
-      params.name = name;
-      params.start = start;
-      params.limit = limit;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableDeleteRowRange_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableScanResponseParams> tableScan(String name,List<int> start,List<int> limit,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableScanParams();
-      params.name = name;
-      params.start = start;
-      params.limit = limit;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableScan_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableGetPermissionsResponseParams> tableGetPermissions(String name,String key,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableGetPermissionsParams();
-      params.name = name;
-      params.key = key;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableGetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableSetPermissionsResponseParams> tableSetPermissions(String name,String prefix,Perms perms,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableSetPermissionsParams();
-      params.name = name;
-      params.prefix = prefix;
-      params.perms = perms;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableSetPermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseTableDeletePermissionsResponseParams> tableDeletePermissions(String name,String prefix,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseTableDeletePermissionsParams();
-      params.name = name;
-      params.prefix = prefix;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_tableDeletePermissions_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseRowExistsResponseParams> rowExists(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseRowExistsParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_rowExists_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseRowGetResponseParams> rowGet(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseRowGetParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_rowGet_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseRowPutResponseParams> rowPut(String name,List<int> value,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseRowPutParams();
-      params.name = name;
-      params.value = value;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_rowPut_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-    Future<SyncbaseRowDeleteResponseParams> rowDelete(String name,[Function responseFactory = null]) {
-      assert(_proxyImpl.isBound);
-      var params = new SyncbaseRowDeleteParams();
-      params.name = name;
-      return _proxyImpl.sendMessageWithRequestId(
-          params,
-          kSyncbase_rowDelete_name,
-          -1,
-          bindings.MessageHeader.kMessageExpectsResponse);
-    }
-}
-
-
-class SyncbaseProxy implements bindings.ProxyBase {
-  final bindings.Proxy impl;
-  Syncbase ptr;
-  final String name = SyncbaseName;
-
-  SyncbaseProxy(SyncbaseProxyImpl proxyImpl) :
-      impl = proxyImpl,
-      ptr = new _SyncbaseProxyCalls(proxyImpl);
-
-  SyncbaseProxy.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) :
-      impl = new SyncbaseProxyImpl.fromEndpoint(endpoint) {
-    ptr = new _SyncbaseProxyCalls(impl);
-  }
-
-  SyncbaseProxy.fromHandle(core.MojoHandle handle) :
-      impl = new SyncbaseProxyImpl.fromHandle(handle) {
-    ptr = new _SyncbaseProxyCalls(impl);
-  }
-
-  SyncbaseProxy.unbound() :
-      impl = new SyncbaseProxyImpl.unbound() {
-    ptr = new _SyncbaseProxyCalls(impl);
-  }
-
-  static SyncbaseProxy newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For SyncbaseProxy"));
-    return new SyncbaseProxy.fromEndpoint(endpoint);
-  }
-
-  Future close({bool immediate: false}) => impl.close(immediate: immediate);
-
-  int get version => impl.version;
-
-  Future<int> queryVersion() => impl.queryVersion();
-
-  void requireVersion(int requiredVersion) {
-    impl.requireVersion(requiredVersion);
-  }
-
-  String toString() {
-    return "SyncbaseProxy($impl)";
-  }
-}
-
-
-class SyncbaseStub extends bindings.Stub {
-  Syncbase _impl = null;
-
-  SyncbaseStub.fromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint, [this._impl])
-      : super.fromEndpoint(endpoint);
-
-  SyncbaseStub.fromHandle(core.MojoHandle handle, [this._impl])
-      : super.fromHandle(handle);
-
-  SyncbaseStub.unbound() : super.unbound();
-
-  static SyncbaseStub newFromEndpoint(
-      core.MojoMessagePipeEndpoint endpoint) {
-    assert(endpoint.setDescription("For SyncbaseStub"));
-    return new SyncbaseStub.fromEndpoint(endpoint);
-  }
-
-  static const String name = SyncbaseName;
-
-
-  SyncbaseServiceGetPermissionsResponseParams _SyncbaseServiceGetPermissionsResponseParamsFactory(Error err, Perms perms, String version) {
-    var result = new SyncbaseServiceGetPermissionsResponseParams();
-    result.err = err;
-    result.perms = perms;
-    result.version = version;
-    return result;
-  }
-  SyncbaseServiceSetPermissionsResponseParams _SyncbaseServiceSetPermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseServiceSetPermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseAppCreateResponseParams _SyncbaseAppCreateResponseParamsFactory(Error err) {
-    var result = new SyncbaseAppCreateResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseAppDeleteResponseParams _SyncbaseAppDeleteResponseParamsFactory(Error err) {
-    var result = new SyncbaseAppDeleteResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseAppExistsResponseParams _SyncbaseAppExistsResponseParamsFactory(Error err, bool exists) {
-    var result = new SyncbaseAppExistsResponseParams();
-    result.err = err;
-    result.exists = exists;
-    return result;
-  }
-  SyncbaseAppGetPermissionsResponseParams _SyncbaseAppGetPermissionsResponseParamsFactory(Error err, Perms perms, String version) {
-    var result = new SyncbaseAppGetPermissionsResponseParams();
-    result.err = err;
-    result.perms = perms;
-    result.version = version;
-    return result;
-  }
-  SyncbaseAppSetPermissionsResponseParams _SyncbaseAppSetPermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseAppSetPermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbCreateResponseParams _SyncbaseDbCreateResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbCreateResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbDeleteResponseParams _SyncbaseDbDeleteResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbDeleteResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbExistsResponseParams _SyncbaseDbExistsResponseParamsFactory(Error err, bool exists) {
-    var result = new SyncbaseDbExistsResponseParams();
-    result.err = err;
-    result.exists = exists;
-    return result;
-  }
-  SyncbaseDbExecResponseParams _SyncbaseDbExecResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbExecResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbBeginBatchResponseParams _SyncbaseDbBeginBatchResponseParamsFactory(Error err, String batchDn) {
-    var result = new SyncbaseDbBeginBatchResponseParams();
-    result.err = err;
-    result.batchDn = batchDn;
-    return result;
-  }
-  SyncbaseDbCommitResponseParams _SyncbaseDbCommitResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbCommitResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbAbortResponseParams _SyncbaseDbAbortResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbAbortResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbGetPermissionsResponseParams _SyncbaseDbGetPermissionsResponseParamsFactory(Error err, Perms perms, String version) {
-    var result = new SyncbaseDbGetPermissionsResponseParams();
-    result.err = err;
-    result.perms = perms;
-    result.version = version;
-    return result;
-  }
-  SyncbaseDbSetPermissionsResponseParams _SyncbaseDbSetPermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbSetPermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbGetSyncGroupNamesResponseParams _SyncbaseDbGetSyncGroupNamesResponseParamsFactory(Error err, List<String> names) {
-    var result = new SyncbaseDbGetSyncGroupNamesResponseParams();
-    result.err = err;
-    result.names = names;
-    return result;
-  }
-  SyncbaseDbCreateSyncGroupResponseParams _SyncbaseDbCreateSyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbCreateSyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbJoinSyncGroupResponseParams _SyncbaseDbJoinSyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbJoinSyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbLeaveSyncGroupResponseParams _SyncbaseDbLeaveSyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbLeaveSyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbDestroySyncGroupResponseParams _SyncbaseDbDestroySyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbDestroySyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbEjectFromSyncGroupResponseParams _SyncbaseDbEjectFromSyncGroupResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbEjectFromSyncGroupResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbGetSyncGroupSpecResponseParams _SyncbaseDbGetSyncGroupSpecResponseParamsFactory(Error err, SyncGroupSpec spec, String version) {
-    var result = new SyncbaseDbGetSyncGroupSpecResponseParams();
-    result.err = err;
-    result.spec = spec;
-    result.version = version;
-    return result;
-  }
-  SyncbaseDbSetSyncGroupSpecResponseParams _SyncbaseDbSetSyncGroupSpecResponseParamsFactory(Error err) {
-    var result = new SyncbaseDbSetSyncGroupSpecResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseDbGetSyncGroupMembersResponseParams _SyncbaseDbGetSyncGroupMembersResponseParamsFactory(Error err, Map<String, SyncGroupMemberInfo> infos) {
-    var result = new SyncbaseDbGetSyncGroupMembersResponseParams();
-    result.err = err;
-    result.infos = infos;
-    return result;
-  }
-  SyncbaseTableCreateResponseParams _SyncbaseTableCreateResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableCreateResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableDeleteResponseParams _SyncbaseTableDeleteResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableDeleteResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableExistsResponseParams _SyncbaseTableExistsResponseParamsFactory(Error err, bool exists) {
-    var result = new SyncbaseTableExistsResponseParams();
-    result.err = err;
-    result.exists = exists;
-    return result;
-  }
-  SyncbaseTableDeleteRowRangeResponseParams _SyncbaseTableDeleteRowRangeResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableDeleteRowRangeResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableScanResponseParams _SyncbaseTableScanResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableScanResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableGetPermissionsResponseParams _SyncbaseTableGetPermissionsResponseParamsFactory(Error err, List<PrefixPerms> permsArr) {
-    var result = new SyncbaseTableGetPermissionsResponseParams();
-    result.err = err;
-    result.permsArr = permsArr;
-    return result;
-  }
-  SyncbaseTableSetPermissionsResponseParams _SyncbaseTableSetPermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableSetPermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseTableDeletePermissionsResponseParams _SyncbaseTableDeletePermissionsResponseParamsFactory(Error err) {
-    var result = new SyncbaseTableDeletePermissionsResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseRowExistsResponseParams _SyncbaseRowExistsResponseParamsFactory(Error err, bool exists) {
-    var result = new SyncbaseRowExistsResponseParams();
-    result.err = err;
-    result.exists = exists;
-    return result;
-  }
-  SyncbaseRowGetResponseParams _SyncbaseRowGetResponseParamsFactory(Error err, List<int> value) {
-    var result = new SyncbaseRowGetResponseParams();
-    result.err = err;
-    result.value = value;
-    return result;
-  }
-  SyncbaseRowPutResponseParams _SyncbaseRowPutResponseParamsFactory(Error err) {
-    var result = new SyncbaseRowPutResponseParams();
-    result.err = err;
-    return result;
-  }
-  SyncbaseRowDeleteResponseParams _SyncbaseRowDeleteResponseParamsFactory(Error err) {
-    var result = new SyncbaseRowDeleteResponseParams();
-    result.err = err;
-    return result;
-  }
-
-  Future<bindings.Message> handleMessage(bindings.ServiceMessage message) {
-    if (bindings.ControlMessageHandler.isControlMessage(message)) {
-      return bindings.ControlMessageHandler.handleMessage(this,
-                                                          0,
-                                                          message);
-    }
-    assert(_impl != null);
-    switch (message.header.type) {
-      case kSyncbase_serviceGetPermissions_name:
-        var params = SyncbaseServiceGetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.serviceGetPermissions(_SyncbaseServiceGetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_serviceGetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_serviceSetPermissions_name:
-        var params = SyncbaseServiceSetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.serviceSetPermissions(params.perms,params.version,_SyncbaseServiceSetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_serviceSetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appCreate_name:
-        var params = SyncbaseAppCreateParams.deserialize(
-            message.payload);
-        return _impl.appCreate(params.name,params.perms,_SyncbaseAppCreateResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appCreate_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appDelete_name:
-        var params = SyncbaseAppDeleteParams.deserialize(
-            message.payload);
-        return _impl.appDelete(params.name,_SyncbaseAppDeleteResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appDelete_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appExists_name:
-        var params = SyncbaseAppExistsParams.deserialize(
-            message.payload);
-        return _impl.appExists(params.name,_SyncbaseAppExistsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appExists_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appGetPermissions_name:
-        var params = SyncbaseAppGetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.appGetPermissions(params.name,_SyncbaseAppGetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appGetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_appSetPermissions_name:
-        var params = SyncbaseAppSetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.appSetPermissions(params.name,params.perms,params.version,_SyncbaseAppSetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_appSetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbCreate_name:
-        var params = SyncbaseDbCreateParams.deserialize(
-            message.payload);
-        return _impl.dbCreate(params.name,params.perms,_SyncbaseDbCreateResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbCreate_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbDelete_name:
-        var params = SyncbaseDbDeleteParams.deserialize(
-            message.payload);
-        return _impl.dbDelete(params.name,_SyncbaseDbDeleteResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbDelete_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbExists_name:
-        var params = SyncbaseDbExistsParams.deserialize(
-            message.payload);
-        return _impl.dbExists(params.name,_SyncbaseDbExistsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbExists_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbExec_name:
-        var params = SyncbaseDbExecParams.deserialize(
-            message.payload);
-        return _impl.dbExec(params.query,_SyncbaseDbExecResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbExec_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbBeginBatch_name:
-        var params = SyncbaseDbBeginBatchParams.deserialize(
-            message.payload);
-        return _impl.dbBeginBatch(params.name,params.bo,_SyncbaseDbBeginBatchResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbBeginBatch_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbCommit_name:
-        var params = SyncbaseDbCommitParams.deserialize(
-            message.payload);
-        return _impl.dbCommit(params.name,_SyncbaseDbCommitResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbCommit_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbAbort_name:
-        var params = SyncbaseDbAbortParams.deserialize(
-            message.payload);
-        return _impl.dbAbort(params.name,_SyncbaseDbAbortResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbAbort_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbGetPermissions_name:
-        var params = SyncbaseDbGetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.dbGetPermissions(params.name,_SyncbaseDbGetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbGetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbSetPermissions_name:
-        var params = SyncbaseDbSetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.dbSetPermissions(params.name,params.perms,params.version,_SyncbaseDbSetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbSetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbGetSyncGroupNames_name:
-        var params = SyncbaseDbGetSyncGroupNamesParams.deserialize(
-            message.payload);
-        return _impl.dbGetSyncGroupNames(params.name,_SyncbaseDbGetSyncGroupNamesResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbGetSyncGroupNames_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbCreateSyncGroup_name:
-        var params = SyncbaseDbCreateSyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbCreateSyncGroup(params.name,params.sgName,params.spec,params.myInfo,_SyncbaseDbCreateSyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbCreateSyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbJoinSyncGroup_name:
-        var params = SyncbaseDbJoinSyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbJoinSyncGroup(params.name,params.sgName,params.myInfo,_SyncbaseDbJoinSyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbJoinSyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbLeaveSyncGroup_name:
-        var params = SyncbaseDbLeaveSyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbLeaveSyncGroup(params.name,params.sgName,_SyncbaseDbLeaveSyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbLeaveSyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbDestroySyncGroup_name:
-        var params = SyncbaseDbDestroySyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbDestroySyncGroup(params.name,params.sgName,_SyncbaseDbDestroySyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbDestroySyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbEjectFromSyncGroup_name:
-        var params = SyncbaseDbEjectFromSyncGroupParams.deserialize(
-            message.payload);
-        return _impl.dbEjectFromSyncGroup(params.name,params.sgName,params.member,_SyncbaseDbEjectFromSyncGroupResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbEjectFromSyncGroup_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbGetSyncGroupSpec_name:
-        var params = SyncbaseDbGetSyncGroupSpecParams.deserialize(
-            message.payload);
-        return _impl.dbGetSyncGroupSpec(params.name,params.sgName,_SyncbaseDbGetSyncGroupSpecResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbGetSyncGroupSpec_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbSetSyncGroupSpec_name:
-        var params = SyncbaseDbSetSyncGroupSpecParams.deserialize(
-            message.payload);
-        return _impl.dbSetSyncGroupSpec(params.name,params.sgName,params.spec,params.version,_SyncbaseDbSetSyncGroupSpecResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbSetSyncGroupSpec_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_dbGetSyncGroupMembers_name:
-        var params = SyncbaseDbGetSyncGroupMembersParams.deserialize(
-            message.payload);
-        return _impl.dbGetSyncGroupMembers(params.name,params.sgName,_SyncbaseDbGetSyncGroupMembersResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_dbGetSyncGroupMembers_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableCreate_name:
-        var params = SyncbaseTableCreateParams.deserialize(
-            message.payload);
-        return _impl.tableCreate(params.name,params.perms,_SyncbaseTableCreateResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableCreate_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableDelete_name:
-        var params = SyncbaseTableDeleteParams.deserialize(
-            message.payload);
-        return _impl.tableDelete(params.name,_SyncbaseTableDeleteResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableDelete_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableExists_name:
-        var params = SyncbaseTableExistsParams.deserialize(
-            message.payload);
-        return _impl.tableExists(params.name,_SyncbaseTableExistsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableExists_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableDeleteRowRange_name:
-        var params = SyncbaseTableDeleteRowRangeParams.deserialize(
-            message.payload);
-        return _impl.tableDeleteRowRange(params.name,params.start,params.limit,_SyncbaseTableDeleteRowRangeResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableDeleteRowRange_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableScan_name:
-        var params = SyncbaseTableScanParams.deserialize(
-            message.payload);
-        return _impl.tableScan(params.name,params.start,params.limit,_SyncbaseTableScanResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableScan_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableGetPermissions_name:
-        var params = SyncbaseTableGetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.tableGetPermissions(params.name,params.key,_SyncbaseTableGetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableGetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableSetPermissions_name:
-        var params = SyncbaseTableSetPermissionsParams.deserialize(
-            message.payload);
-        return _impl.tableSetPermissions(params.name,params.prefix,params.perms,_SyncbaseTableSetPermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableSetPermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_tableDeletePermissions_name:
-        var params = SyncbaseTableDeletePermissionsParams.deserialize(
-            message.payload);
-        return _impl.tableDeletePermissions(params.name,params.prefix,_SyncbaseTableDeletePermissionsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_tableDeletePermissions_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_rowExists_name:
-        var params = SyncbaseRowExistsParams.deserialize(
-            message.payload);
-        return _impl.rowExists(params.name,_SyncbaseRowExistsResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_rowExists_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_rowGet_name:
-        var params = SyncbaseRowGetParams.deserialize(
-            message.payload);
-        return _impl.rowGet(params.name,_SyncbaseRowGetResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_rowGet_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_rowPut_name:
-        var params = SyncbaseRowPutParams.deserialize(
-            message.payload);
-        return _impl.rowPut(params.name,params.value,_SyncbaseRowPutResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_rowPut_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      case kSyncbase_rowDelete_name:
-        var params = SyncbaseRowDeleteParams.deserialize(
-            message.payload);
-        return _impl.rowDelete(params.name,_SyncbaseRowDeleteResponseParamsFactory).then((response) {
-          if (response != null) {
-            return buildResponseWithId(
-                response,
-                kSyncbase_rowDelete_name,
-                message.header.requestId,
-                bindings.MessageHeader.kMessageIsResponse);
-          }
-        });
-        break;
-      default:
-        throw new bindings.MojoCodecError("Unexpected message name");
-        break;
-    }
-    return null;
-  }
-
-  Syncbase get impl => _impl;
-  set impl(Syncbase d) {
-    assert(_impl == null);
-    _impl = d;
-  }
-
-  String toString() {
-    var superString = super.toString();
-    return "SyncbaseStub($superString)";
-  }
-
-  int get version => 0;
-}
-
-
diff --git a/gen/go/src/mojom/echo/echo.mojom.go b/gen/go/src/mojom/echo/echo.mojom.go
deleted file mode 100644
index 7cd504c..0000000
--- a/gen/go/src/mojom/echo/echo.mojom.go
+++ /dev/null
@@ -1,299 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is autogenerated by:
-//     mojo/public/tools/bindings/mojom_bindings_generator.py
-// For:
-//     mojom/echo.mojom
-//
-
-package echo
-
-import (
-	"fmt"
-	"mojo/public/go/bindings"
-	"mojo/public/go/system"
-	"sort"
-)
-
-type Echo interface {
-	EchoString(inValue *string) (outValue *string, err error)
-}
-
-var echo_Name = "mojo::examples::Echo"
-
-type Echo_Request bindings.InterfaceRequest
-
-func (r *Echo_Request) Name() string {
-	return echo_Name
-}
-
-type Echo_Pointer bindings.InterfacePointer
-
-func (p *Echo_Pointer) Name() string {
-	return echo_Name
-}
-
-type Echo_ServiceFactory struct {
-	Delegate Echo_Factory
-}
-
-type Echo_Factory interface {
-	Create(request Echo_Request)
-}
-
-func (f *Echo_ServiceFactory) Name() string {
-	return echo_Name
-}
-
-func (f *Echo_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
-	request := Echo_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
-	f.Delegate.Create(request)
-}
-
-// CreateMessagePipeForEcho creates a message pipe for use with the
-// Echo interface with a Echo_Request on one end and a Echo_Pointer on the other.
-func CreateMessagePipeForEcho() (Echo_Request, Echo_Pointer) {
-	r, p := bindings.CreateMessagePipeForMojoInterface()
-	return Echo_Request(r), Echo_Pointer(p)
-}
-
-const echo_EchoString_Name uint32 = 0
-
-type Echo_Proxy struct {
-	router *bindings.Router
-	ids    bindings.Counter
-}
-
-func NewEchoProxy(p Echo_Pointer, waiter bindings.AsyncWaiter) *Echo_Proxy {
-	return &Echo_Proxy{
-		bindings.NewRouter(p.PassMessagePipe(), waiter),
-		bindings.NewCounter(),
-	}
-}
-
-func (p *Echo_Proxy) Close_Proxy() {
-	p.router.Close()
-}
-
-type echo_EchoString_Params struct {
-	inValue *string
-}
-
-func (s *echo_EchoString_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if s.inValue == nil {
-		encoder.WriteNullPointer()
-	} else {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := encoder.WriteString((*s.inValue)); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var echo_EchoString_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *echo_EchoString_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(echo_EchoString_Params_Versions), func(i int) bool {
-		return echo_EchoString_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(echo_EchoString_Params_Versions) {
-		if echo_EchoString_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := echo_EchoString_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			s.inValue = nil
-		} else {
-			s.inValue = new(string)
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			(*s.inValue) = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type echo_EchoString_ResponseParams struct {
-	outValue *string
-}
-
-func (s *echo_EchoString_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if s.outValue == nil {
-		encoder.WriteNullPointer()
-	} else {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := encoder.WriteString((*s.outValue)); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var echo_EchoString_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *echo_EchoString_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(echo_EchoString_ResponseParams_Versions), func(i int) bool {
-		return echo_EchoString_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(echo_EchoString_ResponseParams_Versions) {
-		if echo_EchoString_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := echo_EchoString_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			s.outValue = nil
-		} else {
-			s.outValue = new(string)
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			(*s.outValue) = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Echo_Proxy) EchoString(inValue *string) (outValue *string, err error) {
-	payload := &echo_EchoString_Params{
-		inValue,
-	}
-	header := bindings.MessageHeader{
-		Type:      echo_EchoString_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, echo_EchoString_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response echo_EchoString_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outValue = response.outValue
-	return
-}
-
-type echo_Stub struct {
-	connector *bindings.Connector
-	impl      Echo
-}
-
-func NewEchoStub(r Echo_Request, impl Echo, waiter bindings.AsyncWaiter) *bindings.Stub {
-	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
-	return bindings.NewStub(connector, &echo_Stub{connector, impl})
-}
-
-func (s *echo_Stub) Accept(message *bindings.Message) (err error) {
-	switch message.Header.Type {
-	case echo_EchoString_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request echo_EchoString_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response echo_EchoString_ResponseParams
-		response.outValue, err = s.impl.EchoString(request.inValue)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      echo_EchoString_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	default:
-		return &bindings.ValidationError{
-			bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("unknown method %v", message.Header.Type),
-		}
-	}
-	return
-}
diff --git a/gen/go/src/mojom/syncbase/syncbase.mojom.go b/gen/go/src/mojom/syncbase/syncbase.mojom.go
deleted file mode 100644
index 0b12996..0000000
--- a/gen/go/src/mojom/syncbase/syncbase.mojom.go
+++ /dev/null
@@ -1,8978 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// This file is autogenerated by:
-//     mojo/public/tools/bindings/mojom_bindings_generator.py
-// For:
-//     mojom/syncbase.mojom
-//
-
-package syncbase
-
-import (
-	"fmt"
-	"mojo/public/go/bindings"
-	"mojo/public/go/system"
-	"sort"
-)
-
-type Syncbase interface {
-	ServiceGetPermissions() (outErr Error, outPerms Perms, outVersion string, err error)
-	ServiceSetPermissions(inPerms Perms, inVersion string) (outErr Error, err error)
-	AppCreate(inName string, inPerms Perms) (outErr Error, err error)
-	AppDelete(inName string) (outErr Error, err error)
-	AppExists(inName string) (outErr Error, outExists bool, err error)
-	AppGetPermissions(inName string) (outErr Error, outPerms Perms, outVersion string, err error)
-	AppSetPermissions(inName string, inPerms Perms, inVersion string) (outErr Error, err error)
-	DbCreate(inName string, inPerms Perms) (outErr Error, err error)
-	DbDelete(inName string) (outErr Error, err error)
-	DbExists(inName string) (outErr Error, outExists bool, err error)
-	DbExec(inQuery string) (outErr Error, err error)
-	DbBeginBatch(inName string, inBo *BatchOptions) (outErr Error, outBatchDn string, err error)
-	DbCommit(inName string) (outErr Error, err error)
-	DbAbort(inName string) (outErr Error, err error)
-	DbGetPermissions(inName string) (outErr Error, outPerms Perms, outVersion string, err error)
-	DbSetPermissions(inName string, inPerms Perms, inVersion string) (outErr Error, err error)
-	DbGetSyncGroupNames(inName string) (outErr Error, outNames []string, err error)
-	DbCreateSyncGroup(inName string, inSgName string, inSpec SyncGroupSpec, inMyInfo SyncGroupMemberInfo) (outErr Error, err error)
-	DbJoinSyncGroup(inName string, inSgName string, inMyInfo SyncGroupMemberInfo) (outErr Error, err error)
-	DbLeaveSyncGroup(inName string, inSgName string) (outErr Error, err error)
-	DbDestroySyncGroup(inName string, inSgName string) (outErr Error, err error)
-	DbEjectFromSyncGroup(inName string, inSgName string, inMember string) (outErr Error, err error)
-	DbGetSyncGroupSpec(inName string, inSgName string) (outErr Error, outSpec SyncGroupSpec, outVersion string, err error)
-	DbSetSyncGroupSpec(inName string, inSgName string, inSpec SyncGroupSpec, inVersion string) (outErr Error, err error)
-	DbGetSyncGroupMembers(inName string, inSgName string) (outErr Error, outInfos map[string]SyncGroupMemberInfo, err error)
-	TableCreate(inName string, inPerms Perms) (outErr Error, err error)
-	TableDelete(inName string) (outErr Error, err error)
-	TableExists(inName string) (outErr Error, outExists bool, err error)
-	TableDeleteRowRange(inName string, inStart []uint8, inLimit []uint8) (outErr Error, err error)
-	TableScan(inName string, inStart []uint8, inLimit []uint8) (outErr Error, err error)
-	TableGetPermissions(inName string, inKey string) (outErr Error, outPermsArr []PrefixPerms, err error)
-	TableSetPermissions(inName string, inPrefix string, inPerms Perms) (outErr Error, err error)
-	TableDeletePermissions(inName string, inPrefix string) (outErr Error, err error)
-	RowExists(inName string) (outErr Error, outExists bool, err error)
-	RowGet(inName string) (outErr Error, outValue []uint8, err error)
-	RowPut(inName string, inValue []uint8) (outErr Error, err error)
-	RowDelete(inName string) (outErr Error, err error)
-}
-
-var syncbase_Name = "mojo::syncbase::Syncbase"
-
-type Syncbase_Request bindings.InterfaceRequest
-
-func (r *Syncbase_Request) Name() string {
-	return syncbase_Name
-}
-
-type Syncbase_Pointer bindings.InterfacePointer
-
-func (p *Syncbase_Pointer) Name() string {
-	return syncbase_Name
-}
-
-type Syncbase_ServiceFactory struct {
-	Delegate Syncbase_Factory
-}
-
-type Syncbase_Factory interface {
-	Create(request Syncbase_Request)
-}
-
-func (f *Syncbase_ServiceFactory) Name() string {
-	return syncbase_Name
-}
-
-func (f *Syncbase_ServiceFactory) Create(messagePipe system.MessagePipeHandle) {
-	request := Syncbase_Request{bindings.NewMessagePipeHandleOwner(messagePipe)}
-	f.Delegate.Create(request)
-}
-
-// CreateMessagePipeForSyncbase creates a message pipe for use with the
-// Syncbase interface with a Syncbase_Request on one end and a Syncbase_Pointer on the other.
-func CreateMessagePipeForSyncbase() (Syncbase_Request, Syncbase_Pointer) {
-	r, p := bindings.CreateMessagePipeForMojoInterface()
-	return Syncbase_Request(r), Syncbase_Pointer(p)
-}
-
-const syncbase_ServiceGetPermissions_Name uint32 = 0
-const syncbase_ServiceSetPermissions_Name uint32 = 1
-const syncbase_AppCreate_Name uint32 = 2
-const syncbase_AppDelete_Name uint32 = 3
-const syncbase_AppExists_Name uint32 = 4
-const syncbase_AppGetPermissions_Name uint32 = 5
-const syncbase_AppSetPermissions_Name uint32 = 6
-const syncbase_DbCreate_Name uint32 = 7
-const syncbase_DbDelete_Name uint32 = 8
-const syncbase_DbExists_Name uint32 = 9
-const syncbase_DbExec_Name uint32 = 10
-const syncbase_DbBeginBatch_Name uint32 = 11
-const syncbase_DbCommit_Name uint32 = 12
-const syncbase_DbAbort_Name uint32 = 13
-const syncbase_DbGetPermissions_Name uint32 = 14
-const syncbase_DbSetPermissions_Name uint32 = 15
-const syncbase_DbGetSyncGroupNames_Name uint32 = 16
-const syncbase_DbCreateSyncGroup_Name uint32 = 17
-const syncbase_DbJoinSyncGroup_Name uint32 = 18
-const syncbase_DbLeaveSyncGroup_Name uint32 = 19
-const syncbase_DbDestroySyncGroup_Name uint32 = 20
-const syncbase_DbEjectFromSyncGroup_Name uint32 = 21
-const syncbase_DbGetSyncGroupSpec_Name uint32 = 22
-const syncbase_DbSetSyncGroupSpec_Name uint32 = 23
-const syncbase_DbGetSyncGroupMembers_Name uint32 = 24
-const syncbase_TableCreate_Name uint32 = 25
-const syncbase_TableDelete_Name uint32 = 26
-const syncbase_TableExists_Name uint32 = 27
-const syncbase_TableDeleteRowRange_Name uint32 = 28
-const syncbase_TableScan_Name uint32 = 29
-const syncbase_TableGetPermissions_Name uint32 = 30
-const syncbase_TableSetPermissions_Name uint32 = 31
-const syncbase_TableDeletePermissions_Name uint32 = 32
-const syncbase_RowExists_Name uint32 = 33
-const syncbase_RowGet_Name uint32 = 34
-const syncbase_RowPut_Name uint32 = 35
-const syncbase_RowDelete_Name uint32 = 36
-
-type Syncbase_Proxy struct {
-	router *bindings.Router
-	ids    bindings.Counter
-}
-
-func NewSyncbaseProxy(p Syncbase_Pointer, waiter bindings.AsyncWaiter) *Syncbase_Proxy {
-	return &Syncbase_Proxy{
-		bindings.NewRouter(p.PassMessagePipe(), waiter),
-		bindings.NewCounter(),
-	}
-}
-
-func (p *Syncbase_Proxy) Close_Proxy() {
-	p.router.Close()
-}
-
-type syncbase_ServiceGetPermissions_Params struct {
-}
-
-func (s *syncbase_ServiceGetPermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(0, 0)
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_ServiceGetPermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{8, 0},
-}
-
-func (s *syncbase_ServiceGetPermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_ServiceGetPermissions_Params_Versions), func(i int) bool {
-		return syncbase_ServiceGetPermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_ServiceGetPermissions_Params_Versions) {
-		if syncbase_ServiceGetPermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_ServiceGetPermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_ServiceGetPermissions_ResponseParams struct {
-	outErr     Error
-	outPerms   Perms
-	outVersion string
-}
-
-func (s *syncbase_ServiceGetPermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.outVersion); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_ServiceGetPermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_ServiceGetPermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_ServiceGetPermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_ServiceGetPermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_ServiceGetPermissions_ResponseParams_Versions) {
-		if syncbase_ServiceGetPermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_ServiceGetPermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.outVersion = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) ServiceGetPermissions() (outErr Error, outPerms Perms, outVersion string, err error) {
-	payload := &syncbase_ServiceGetPermissions_Params{}
-	header := bindings.MessageHeader{
-		Type:      syncbase_ServiceGetPermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_ServiceGetPermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_ServiceGetPermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outPerms = response.outPerms
-	outVersion = response.outVersion
-	return
-}
-
-type syncbase_ServiceSetPermissions_Params struct {
-	inPerms   Perms
-	inVersion string
-}
-
-func (s *syncbase_ServiceSetPermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inVersion); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_ServiceSetPermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_ServiceSetPermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_ServiceSetPermissions_Params_Versions), func(i int) bool {
-		return syncbase_ServiceSetPermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_ServiceSetPermissions_Params_Versions) {
-		if syncbase_ServiceSetPermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_ServiceSetPermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inVersion = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_ServiceSetPermissions_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_ServiceSetPermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_ServiceSetPermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_ServiceSetPermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_ServiceSetPermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_ServiceSetPermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_ServiceSetPermissions_ResponseParams_Versions) {
-		if syncbase_ServiceSetPermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_ServiceSetPermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) ServiceSetPermissions(inPerms Perms, inVersion string) (outErr Error, err error) {
-	payload := &syncbase_ServiceSetPermissions_Params{
-		inPerms,
-		inVersion,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_ServiceSetPermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_ServiceSetPermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_ServiceSetPermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_AppCreate_Params struct {
-	inName  string
-	inPerms Perms
-}
-
-func (s *syncbase_AppCreate_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppCreate_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_AppCreate_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppCreate_Params_Versions), func(i int) bool {
-		return syncbase_AppCreate_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppCreate_Params_Versions) {
-		if syncbase_AppCreate_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppCreate_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_AppCreate_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_AppCreate_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppCreate_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_AppCreate_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppCreate_ResponseParams_Versions), func(i int) bool {
-		return syncbase_AppCreate_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppCreate_ResponseParams_Versions) {
-		if syncbase_AppCreate_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppCreate_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) AppCreate(inName string, inPerms Perms) (outErr Error, err error) {
-	payload := &syncbase_AppCreate_Params{
-		inName,
-		inPerms,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_AppCreate_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_AppCreate_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_AppCreate_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_AppDelete_Params struct {
-	inName string
-}
-
-func (s *syncbase_AppDelete_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppDelete_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_AppDelete_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppDelete_Params_Versions), func(i int) bool {
-		return syncbase_AppDelete_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppDelete_Params_Versions) {
-		if syncbase_AppDelete_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppDelete_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_AppDelete_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_AppDelete_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppDelete_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_AppDelete_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppDelete_ResponseParams_Versions), func(i int) bool {
-		return syncbase_AppDelete_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppDelete_ResponseParams_Versions) {
-		if syncbase_AppDelete_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppDelete_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) AppDelete(inName string) (outErr Error, err error) {
-	payload := &syncbase_AppDelete_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_AppDelete_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_AppDelete_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_AppDelete_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_AppExists_Params struct {
-	inName string
-}
-
-func (s *syncbase_AppExists_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppExists_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_AppExists_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppExists_Params_Versions), func(i int) bool {
-		return syncbase_AppExists_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppExists_Params_Versions) {
-		if syncbase_AppExists_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppExists_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_AppExists_ResponseParams struct {
-	outErr    Error
-	outExists bool
-}
-
-func (s *syncbase_AppExists_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WriteBool(s.outExists); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppExists_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_AppExists_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppExists_ResponseParams_Versions), func(i int) bool {
-		return syncbase_AppExists_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppExists_ResponseParams_Versions) {
-		if syncbase_AppExists_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppExists_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadBool()
-		if err != nil {
-			return err
-		}
-		s.outExists = value0
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) AppExists(inName string) (outErr Error, outExists bool, err error) {
-	payload := &syncbase_AppExists_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_AppExists_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_AppExists_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_AppExists_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outExists = response.outExists
-	return
-}
-
-type syncbase_AppGetPermissions_Params struct {
-	inName string
-}
-
-func (s *syncbase_AppGetPermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppGetPermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_AppGetPermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppGetPermissions_Params_Versions), func(i int) bool {
-		return syncbase_AppGetPermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppGetPermissions_Params_Versions) {
-		if syncbase_AppGetPermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppGetPermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_AppGetPermissions_ResponseParams struct {
-	outErr     Error
-	outPerms   Perms
-	outVersion string
-}
-
-func (s *syncbase_AppGetPermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.outVersion); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppGetPermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_AppGetPermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppGetPermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_AppGetPermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppGetPermissions_ResponseParams_Versions) {
-		if syncbase_AppGetPermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppGetPermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.outVersion = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) AppGetPermissions(inName string) (outErr Error, outPerms Perms, outVersion string, err error) {
-	payload := &syncbase_AppGetPermissions_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_AppGetPermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_AppGetPermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_AppGetPermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outPerms = response.outPerms
-	outVersion = response.outVersion
-	return
-}
-
-type syncbase_AppSetPermissions_Params struct {
-	inName    string
-	inPerms   Perms
-	inVersion string
-}
-
-func (s *syncbase_AppSetPermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inVersion); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppSetPermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_AppSetPermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppSetPermissions_Params_Versions), func(i int) bool {
-		return syncbase_AppSetPermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppSetPermissions_Params_Versions) {
-		if syncbase_AppSetPermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppSetPermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inVersion = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_AppSetPermissions_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_AppSetPermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_AppSetPermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_AppSetPermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_AppSetPermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_AppSetPermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_AppSetPermissions_ResponseParams_Versions) {
-		if syncbase_AppSetPermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_AppSetPermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) AppSetPermissions(inName string, inPerms Perms, inVersion string) (outErr Error, err error) {
-	payload := &syncbase_AppSetPermissions_Params{
-		inName,
-		inPerms,
-		inVersion,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_AppSetPermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_AppSetPermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_AppSetPermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbCreate_Params struct {
-	inName  string
-	inPerms Perms
-}
-
-func (s *syncbase_DbCreate_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbCreate_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbCreate_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbCreate_Params_Versions), func(i int) bool {
-		return syncbase_DbCreate_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbCreate_Params_Versions) {
-		if syncbase_DbCreate_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbCreate_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbCreate_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbCreate_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbCreate_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbCreate_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbCreate_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbCreate_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbCreate_ResponseParams_Versions) {
-		if syncbase_DbCreate_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbCreate_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbCreate(inName string, inPerms Perms) (outErr Error, err error) {
-	payload := &syncbase_DbCreate_Params{
-		inName,
-		inPerms,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbCreate_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbCreate_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbCreate_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbDelete_Params struct {
-	inName string
-}
-
-func (s *syncbase_DbDelete_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbDelete_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbDelete_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbDelete_Params_Versions), func(i int) bool {
-		return syncbase_DbDelete_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbDelete_Params_Versions) {
-		if syncbase_DbDelete_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbDelete_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbDelete_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbDelete_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbDelete_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbDelete_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbDelete_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbDelete_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbDelete_ResponseParams_Versions) {
-		if syncbase_DbDelete_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbDelete_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbDelete(inName string) (outErr Error, err error) {
-	payload := &syncbase_DbDelete_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbDelete_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbDelete_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbDelete_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbExists_Params struct {
-	inName string
-}
-
-func (s *syncbase_DbExists_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbExists_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbExists_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbExists_Params_Versions), func(i int) bool {
-		return syncbase_DbExists_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbExists_Params_Versions) {
-		if syncbase_DbExists_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbExists_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbExists_ResponseParams struct {
-	outErr    Error
-	outExists bool
-}
-
-func (s *syncbase_DbExists_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WriteBool(s.outExists); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbExists_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbExists_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbExists_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbExists_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbExists_ResponseParams_Versions) {
-		if syncbase_DbExists_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbExists_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadBool()
-		if err != nil {
-			return err
-		}
-		s.outExists = value0
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbExists(inName string) (outErr Error, outExists bool, err error) {
-	payload := &syncbase_DbExists_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbExists_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbExists_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbExists_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outExists = response.outExists
-	return
-}
-
-type syncbase_DbExec_Params struct {
-	inQuery string
-}
-
-func (s *syncbase_DbExec_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inQuery); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbExec_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbExec_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbExec_Params_Versions), func(i int) bool {
-		return syncbase_DbExec_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbExec_Params_Versions) {
-		if syncbase_DbExec_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbExec_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inQuery = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbExec_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbExec_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbExec_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbExec_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbExec_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbExec_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbExec_ResponseParams_Versions) {
-		if syncbase_DbExec_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbExec_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbExec(inQuery string) (outErr Error, err error) {
-	payload := &syncbase_DbExec_Params{
-		inQuery,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbExec_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbExec_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbExec_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbBeginBatch_Params struct {
-	inName string
-	inBo   *BatchOptions
-}
-
-func (s *syncbase_DbBeginBatch_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if s.inBo == nil {
-		encoder.WriteNullPointer()
-	} else {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := (*s.inBo).Encode(encoder); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbBeginBatch_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbBeginBatch_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbBeginBatch_Params_Versions), func(i int) bool {
-		return syncbase_DbBeginBatch_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbBeginBatch_Params_Versions) {
-		if syncbase_DbBeginBatch_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbBeginBatch_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			s.inBo = nil
-		} else {
-			s.inBo = new(BatchOptions)
-			if err := (*s.inBo).Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbBeginBatch_ResponseParams struct {
-	outErr     Error
-	outBatchDn string
-}
-
-func (s *syncbase_DbBeginBatch_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.outBatchDn); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbBeginBatch_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbBeginBatch_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbBeginBatch_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbBeginBatch_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbBeginBatch_ResponseParams_Versions) {
-		if syncbase_DbBeginBatch_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbBeginBatch_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.outBatchDn = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbBeginBatch(inName string, inBo *BatchOptions) (outErr Error, outBatchDn string, err error) {
-	payload := &syncbase_DbBeginBatch_Params{
-		inName,
-		inBo,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbBeginBatch_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbBeginBatch_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbBeginBatch_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outBatchDn = response.outBatchDn
-	return
-}
-
-type syncbase_DbCommit_Params struct {
-	inName string
-}
-
-func (s *syncbase_DbCommit_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbCommit_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbCommit_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbCommit_Params_Versions), func(i int) bool {
-		return syncbase_DbCommit_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbCommit_Params_Versions) {
-		if syncbase_DbCommit_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbCommit_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbCommit_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbCommit_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbCommit_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbCommit_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbCommit_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbCommit_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbCommit_ResponseParams_Versions) {
-		if syncbase_DbCommit_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbCommit_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbCommit(inName string) (outErr Error, err error) {
-	payload := &syncbase_DbCommit_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbCommit_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbCommit_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbCommit_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbAbort_Params struct {
-	inName string
-}
-
-func (s *syncbase_DbAbort_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbAbort_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbAbort_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbAbort_Params_Versions), func(i int) bool {
-		return syncbase_DbAbort_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbAbort_Params_Versions) {
-		if syncbase_DbAbort_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbAbort_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbAbort_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbAbort_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbAbort_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbAbort_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbAbort_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbAbort_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbAbort_ResponseParams_Versions) {
-		if syncbase_DbAbort_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbAbort_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbAbort(inName string) (outErr Error, err error) {
-	payload := &syncbase_DbAbort_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbAbort_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbAbort_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbAbort_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbGetPermissions_Params struct {
-	inName string
-}
-
-func (s *syncbase_DbGetPermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbGetPermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbGetPermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbGetPermissions_Params_Versions), func(i int) bool {
-		return syncbase_DbGetPermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbGetPermissions_Params_Versions) {
-		if syncbase_DbGetPermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbGetPermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbGetPermissions_ResponseParams struct {
-	outErr     Error
-	outPerms   Perms
-	outVersion string
-}
-
-func (s *syncbase_DbGetPermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.outVersion); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbGetPermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_DbGetPermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbGetPermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbGetPermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbGetPermissions_ResponseParams_Versions) {
-		if syncbase_DbGetPermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbGetPermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.outVersion = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbGetPermissions(inName string) (outErr Error, outPerms Perms, outVersion string, err error) {
-	payload := &syncbase_DbGetPermissions_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbGetPermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbGetPermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbGetPermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outPerms = response.outPerms
-	outVersion = response.outVersion
-	return
-}
-
-type syncbase_DbSetPermissions_Params struct {
-	inName    string
-	inPerms   Perms
-	inVersion string
-}
-
-func (s *syncbase_DbSetPermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inVersion); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbSetPermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_DbSetPermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbSetPermissions_Params_Versions), func(i int) bool {
-		return syncbase_DbSetPermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbSetPermissions_Params_Versions) {
-		if syncbase_DbSetPermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbSetPermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inVersion = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbSetPermissions_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbSetPermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbSetPermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbSetPermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbSetPermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbSetPermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbSetPermissions_ResponseParams_Versions) {
-		if syncbase_DbSetPermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbSetPermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbSetPermissions(inName string, inPerms Perms, inVersion string) (outErr Error, err error) {
-	payload := &syncbase_DbSetPermissions_Params{
-		inName,
-		inPerms,
-		inVersion,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbSetPermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbSetPermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbSetPermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbGetSyncGroupNames_Params struct {
-	inName string
-}
-
-func (s *syncbase_DbGetSyncGroupNames_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbGetSyncGroupNames_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbGetSyncGroupNames_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbGetSyncGroupNames_Params_Versions), func(i int) bool {
-		return syncbase_DbGetSyncGroupNames_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbGetSyncGroupNames_Params_Versions) {
-		if syncbase_DbGetSyncGroupNames_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbGetSyncGroupNames_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbGetSyncGroupNames_ResponseParams struct {
-	outErr   Error
-	outNames []string
-}
-
-func (s *syncbase_DbGetSyncGroupNames_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.outNames)), 64)
-	for _, elem0 := range s.outNames {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := encoder.WriteString(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbGetSyncGroupNames_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbGetSyncGroupNames_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbGetSyncGroupNames_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbGetSyncGroupNames_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbGetSyncGroupNames_ResponseParams_Versions) {
-		if syncbase_DbGetSyncGroupNames_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbGetSyncGroupNames_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(64)
-			if err != nil {
-				return err
-			}
-			s.outNames = make([]string, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				pointer1, err := decoder.ReadPointer()
-				if err != nil {
-					return err
-				}
-				if pointer1 == 0 {
-					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-				} else {
-					value1, err := decoder.ReadString()
-					if err != nil {
-						return err
-					}
-					s.outNames[i0] = value1
-				}
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbGetSyncGroupNames(inName string) (outErr Error, outNames []string, err error) {
-	payload := &syncbase_DbGetSyncGroupNames_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbGetSyncGroupNames_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbGetSyncGroupNames_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbGetSyncGroupNames_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outNames = response.outNames
-	return
-}
-
-type syncbase_DbCreateSyncGroup_Params struct {
-	inName   string
-	inSgName string
-	inSpec   SyncGroupSpec
-	inMyInfo SyncGroupMemberInfo
-}
-
-func (s *syncbase_DbCreateSyncGroup_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(32, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inSgName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inSpec.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inMyInfo.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbCreateSyncGroup_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{40, 0},
-}
-
-func (s *syncbase_DbCreateSyncGroup_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbCreateSyncGroup_Params_Versions), func(i int) bool {
-		return syncbase_DbCreateSyncGroup_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbCreateSyncGroup_Params_Versions) {
-		if syncbase_DbCreateSyncGroup_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbCreateSyncGroup_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inSgName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inSpec.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inMyInfo.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbCreateSyncGroup_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbCreateSyncGroup_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbCreateSyncGroup_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbCreateSyncGroup_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbCreateSyncGroup_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbCreateSyncGroup_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbCreateSyncGroup_ResponseParams_Versions) {
-		if syncbase_DbCreateSyncGroup_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbCreateSyncGroup_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbCreateSyncGroup(inName string, inSgName string, inSpec SyncGroupSpec, inMyInfo SyncGroupMemberInfo) (outErr Error, err error) {
-	payload := &syncbase_DbCreateSyncGroup_Params{
-		inName,
-		inSgName,
-		inSpec,
-		inMyInfo,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbCreateSyncGroup_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbCreateSyncGroup_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbCreateSyncGroup_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbJoinSyncGroup_Params struct {
-	inName   string
-	inSgName string
-	inMyInfo SyncGroupMemberInfo
-}
-
-func (s *syncbase_DbJoinSyncGroup_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inSgName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inMyInfo.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbJoinSyncGroup_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_DbJoinSyncGroup_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbJoinSyncGroup_Params_Versions), func(i int) bool {
-		return syncbase_DbJoinSyncGroup_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbJoinSyncGroup_Params_Versions) {
-		if syncbase_DbJoinSyncGroup_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbJoinSyncGroup_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inSgName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inMyInfo.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbJoinSyncGroup_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbJoinSyncGroup_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbJoinSyncGroup_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbJoinSyncGroup_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbJoinSyncGroup_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbJoinSyncGroup_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbJoinSyncGroup_ResponseParams_Versions) {
-		if syncbase_DbJoinSyncGroup_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbJoinSyncGroup_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbJoinSyncGroup(inName string, inSgName string, inMyInfo SyncGroupMemberInfo) (outErr Error, err error) {
-	payload := &syncbase_DbJoinSyncGroup_Params{
-		inName,
-		inSgName,
-		inMyInfo,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbJoinSyncGroup_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbJoinSyncGroup_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbJoinSyncGroup_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbLeaveSyncGroup_Params struct {
-	inName   string
-	inSgName string
-}
-
-func (s *syncbase_DbLeaveSyncGroup_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inSgName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbLeaveSyncGroup_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbLeaveSyncGroup_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbLeaveSyncGroup_Params_Versions), func(i int) bool {
-		return syncbase_DbLeaveSyncGroup_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbLeaveSyncGroup_Params_Versions) {
-		if syncbase_DbLeaveSyncGroup_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbLeaveSyncGroup_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inSgName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbLeaveSyncGroup_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbLeaveSyncGroup_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbLeaveSyncGroup_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbLeaveSyncGroup_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbLeaveSyncGroup_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbLeaveSyncGroup_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbLeaveSyncGroup_ResponseParams_Versions) {
-		if syncbase_DbLeaveSyncGroup_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbLeaveSyncGroup_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbLeaveSyncGroup(inName string, inSgName string) (outErr Error, err error) {
-	payload := &syncbase_DbLeaveSyncGroup_Params{
-		inName,
-		inSgName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbLeaveSyncGroup_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbLeaveSyncGroup_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbLeaveSyncGroup_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbDestroySyncGroup_Params struct {
-	inName   string
-	inSgName string
-}
-
-func (s *syncbase_DbDestroySyncGroup_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inSgName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbDestroySyncGroup_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbDestroySyncGroup_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbDestroySyncGroup_Params_Versions), func(i int) bool {
-		return syncbase_DbDestroySyncGroup_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbDestroySyncGroup_Params_Versions) {
-		if syncbase_DbDestroySyncGroup_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbDestroySyncGroup_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inSgName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbDestroySyncGroup_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbDestroySyncGroup_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbDestroySyncGroup_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbDestroySyncGroup_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbDestroySyncGroup_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbDestroySyncGroup_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbDestroySyncGroup_ResponseParams_Versions) {
-		if syncbase_DbDestroySyncGroup_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbDestroySyncGroup_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbDestroySyncGroup(inName string, inSgName string) (outErr Error, err error) {
-	payload := &syncbase_DbDestroySyncGroup_Params{
-		inName,
-		inSgName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbDestroySyncGroup_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbDestroySyncGroup_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbDestroySyncGroup_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbEjectFromSyncGroup_Params struct {
-	inName   string
-	inSgName string
-	inMember string
-}
-
-func (s *syncbase_DbEjectFromSyncGroup_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inSgName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inMember); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbEjectFromSyncGroup_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_DbEjectFromSyncGroup_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbEjectFromSyncGroup_Params_Versions), func(i int) bool {
-		return syncbase_DbEjectFromSyncGroup_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbEjectFromSyncGroup_Params_Versions) {
-		if syncbase_DbEjectFromSyncGroup_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbEjectFromSyncGroup_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inSgName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inMember = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbEjectFromSyncGroup_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbEjectFromSyncGroup_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbEjectFromSyncGroup_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbEjectFromSyncGroup_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbEjectFromSyncGroup_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbEjectFromSyncGroup_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbEjectFromSyncGroup_ResponseParams_Versions) {
-		if syncbase_DbEjectFromSyncGroup_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbEjectFromSyncGroup_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbEjectFromSyncGroup(inName string, inSgName string, inMember string) (outErr Error, err error) {
-	payload := &syncbase_DbEjectFromSyncGroup_Params{
-		inName,
-		inSgName,
-		inMember,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbEjectFromSyncGroup_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbEjectFromSyncGroup_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbEjectFromSyncGroup_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbGetSyncGroupSpec_Params struct {
-	inName   string
-	inSgName string
-}
-
-func (s *syncbase_DbGetSyncGroupSpec_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inSgName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbGetSyncGroupSpec_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbGetSyncGroupSpec_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbGetSyncGroupSpec_Params_Versions), func(i int) bool {
-		return syncbase_DbGetSyncGroupSpec_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbGetSyncGroupSpec_Params_Versions) {
-		if syncbase_DbGetSyncGroupSpec_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbGetSyncGroupSpec_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inSgName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbGetSyncGroupSpec_ResponseParams struct {
-	outErr     Error
-	outSpec    SyncGroupSpec
-	outVersion string
-}
-
-func (s *syncbase_DbGetSyncGroupSpec_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outSpec.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.outVersion); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbGetSyncGroupSpec_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_DbGetSyncGroupSpec_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbGetSyncGroupSpec_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbGetSyncGroupSpec_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbGetSyncGroupSpec_ResponseParams_Versions) {
-		if syncbase_DbGetSyncGroupSpec_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbGetSyncGroupSpec_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outSpec.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.outVersion = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbGetSyncGroupSpec(inName string, inSgName string) (outErr Error, outSpec SyncGroupSpec, outVersion string, err error) {
-	payload := &syncbase_DbGetSyncGroupSpec_Params{
-		inName,
-		inSgName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbGetSyncGroupSpec_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbGetSyncGroupSpec_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbGetSyncGroupSpec_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outSpec = response.outSpec
-	outVersion = response.outVersion
-	return
-}
-
-type syncbase_DbSetSyncGroupSpec_Params struct {
-	inName    string
-	inSgName  string
-	inSpec    SyncGroupSpec
-	inVersion string
-}
-
-func (s *syncbase_DbSetSyncGroupSpec_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(32, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inSgName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inSpec.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inVersion); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbSetSyncGroupSpec_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{40, 0},
-}
-
-func (s *syncbase_DbSetSyncGroupSpec_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbSetSyncGroupSpec_Params_Versions), func(i int) bool {
-		return syncbase_DbSetSyncGroupSpec_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbSetSyncGroupSpec_Params_Versions) {
-		if syncbase_DbSetSyncGroupSpec_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbSetSyncGroupSpec_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inSgName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inSpec.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inVersion = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbSetSyncGroupSpec_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_DbSetSyncGroupSpec_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbSetSyncGroupSpec_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_DbSetSyncGroupSpec_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbSetSyncGroupSpec_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbSetSyncGroupSpec_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbSetSyncGroupSpec_ResponseParams_Versions) {
-		if syncbase_DbSetSyncGroupSpec_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbSetSyncGroupSpec_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbSetSyncGroupSpec(inName string, inSgName string, inSpec SyncGroupSpec, inVersion string) (outErr Error, err error) {
-	payload := &syncbase_DbSetSyncGroupSpec_Params{
-		inName,
-		inSgName,
-		inSpec,
-		inVersion,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbSetSyncGroupSpec_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbSetSyncGroupSpec_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbSetSyncGroupSpec_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_DbGetSyncGroupMembers_Params struct {
-	inName   string
-	inSgName string
-}
-
-func (s *syncbase_DbGetSyncGroupMembers_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inSgName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbGetSyncGroupMembers_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbGetSyncGroupMembers_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbGetSyncGroupMembers_Params_Versions), func(i int) bool {
-		return syncbase_DbGetSyncGroupMembers_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbGetSyncGroupMembers_Params_Versions) {
-		if syncbase_DbGetSyncGroupMembers_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbGetSyncGroupMembers_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inSgName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_DbGetSyncGroupMembers_ResponseParams struct {
-	outErr   Error
-	outInfos map[string]SyncGroupMemberInfo
-}
-
-func (s *syncbase_DbGetSyncGroupMembers_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartMap()
-	{
-		var keys0 []string
-		var values0 []SyncGroupMemberInfo
-		for key0, value0 := range s.outInfos {
-			keys0 = append(keys0, key0)
-			values0 = append(values0, value0)
-		}
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		encoder.StartArray(uint32(len(keys0)), 64)
-		for _, elem1 := range keys0 {
-			if err := encoder.WritePointer(); err != nil {
-				return err
-			}
-			if err := encoder.WriteString(elem1); err != nil {
-				return err
-			}
-		}
-		if err := encoder.Finish(); err != nil {
-			return err
-		}
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		encoder.StartArray(uint32(len(values0)), 64)
-		for _, elem1 := range values0 {
-			if err := encoder.WritePointer(); err != nil {
-				return err
-			}
-			if err := elem1.Encode(encoder); err != nil {
-				return err
-			}
-		}
-		if err := encoder.Finish(); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_DbGetSyncGroupMembers_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_DbGetSyncGroupMembers_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_DbGetSyncGroupMembers_ResponseParams_Versions), func(i int) bool {
-		return syncbase_DbGetSyncGroupMembers_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_DbGetSyncGroupMembers_ResponseParams_Versions) {
-		if syncbase_DbGetSyncGroupMembers_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_DbGetSyncGroupMembers_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := decoder.StartMap(); err != nil {
-				return err
-			}
-			var keys0 []string
-			{
-				pointer1, err := decoder.ReadPointer()
-				if err != nil {
-					return err
-				}
-				if pointer1 == 0 {
-					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-				} else {
-					len1, err := decoder.StartArray(64)
-					if err != nil {
-						return err
-					}
-					keys0 = make([]string, len1)
-					for i1 := uint32(0); i1 < len1; i1++ {
-						pointer2, err := decoder.ReadPointer()
-						if err != nil {
-							return err
-						}
-						if pointer2 == 0 {
-							return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-						} else {
-							value2, err := decoder.ReadString()
-							if err != nil {
-								return err
-							}
-							keys0[i1] = value2
-						}
-					}
-					if err := decoder.Finish(); err != nil {
-						return err
-					}
-				}
-			}
-			var values0 []SyncGroupMemberInfo
-			{
-				pointer1, err := decoder.ReadPointer()
-				if err != nil {
-					return err
-				}
-				if pointer1 == 0 {
-					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-				} else {
-					len1, err := decoder.StartArray(64)
-					if err != nil {
-						return err
-					}
-					values0 = make([]SyncGroupMemberInfo, len1)
-					for i1 := uint32(0); i1 < len1; i1++ {
-						pointer2, err := decoder.ReadPointer()
-						if err != nil {
-							return err
-						}
-						if pointer2 == 0 {
-							return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-						} else {
-							if err := values0[i1].Decode(decoder); err != nil {
-								return err
-							}
-						}
-					}
-					if err := decoder.Finish(); err != nil {
-						return err
-					}
-				}
-			}
-			if len(keys0) != len(values0) {
-				return &bindings.ValidationError{bindings.DifferentSizedArraysInMap,
-					fmt.Sprintf("Number of keys %d is different from number of values %d", len(keys0), len(values0)),
-				}
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-			len0 := len(keys0)
-			map0 := make(map[string]SyncGroupMemberInfo)
-			for i0 := 0; i0 < len0; i0++ {
-				map0[keys0[i0]] = values0[i0]
-			}
-			s.outInfos = map0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) DbGetSyncGroupMembers(inName string, inSgName string) (outErr Error, outInfos map[string]SyncGroupMemberInfo, err error) {
-	payload := &syncbase_DbGetSyncGroupMembers_Params{
-		inName,
-		inSgName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_DbGetSyncGroupMembers_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_DbGetSyncGroupMembers_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_DbGetSyncGroupMembers_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outInfos = response.outInfos
-	return
-}
-
-type syncbase_TableCreate_Params struct {
-	inName  string
-	inPerms Perms
-}
-
-func (s *syncbase_TableCreate_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableCreate_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_TableCreate_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableCreate_Params_Versions), func(i int) bool {
-		return syncbase_TableCreate_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableCreate_Params_Versions) {
-		if syncbase_TableCreate_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableCreate_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_TableCreate_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_TableCreate_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableCreate_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_TableCreate_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableCreate_ResponseParams_Versions), func(i int) bool {
-		return syncbase_TableCreate_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableCreate_ResponseParams_Versions) {
-		if syncbase_TableCreate_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableCreate_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) TableCreate(inName string, inPerms Perms) (outErr Error, err error) {
-	payload := &syncbase_TableCreate_Params{
-		inName,
-		inPerms,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_TableCreate_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_TableCreate_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_TableCreate_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_TableDelete_Params struct {
-	inName string
-}
-
-func (s *syncbase_TableDelete_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableDelete_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_TableDelete_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableDelete_Params_Versions), func(i int) bool {
-		return syncbase_TableDelete_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableDelete_Params_Versions) {
-		if syncbase_TableDelete_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableDelete_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_TableDelete_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_TableDelete_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableDelete_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_TableDelete_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableDelete_ResponseParams_Versions), func(i int) bool {
-		return syncbase_TableDelete_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableDelete_ResponseParams_Versions) {
-		if syncbase_TableDelete_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableDelete_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) TableDelete(inName string) (outErr Error, err error) {
-	payload := &syncbase_TableDelete_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_TableDelete_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_TableDelete_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_TableDelete_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_TableExists_Params struct {
-	inName string
-}
-
-func (s *syncbase_TableExists_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableExists_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_TableExists_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableExists_Params_Versions), func(i int) bool {
-		return syncbase_TableExists_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableExists_Params_Versions) {
-		if syncbase_TableExists_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableExists_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_TableExists_ResponseParams struct {
-	outErr    Error
-	outExists bool
-}
-
-func (s *syncbase_TableExists_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WriteBool(s.outExists); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableExists_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_TableExists_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableExists_ResponseParams_Versions), func(i int) bool {
-		return syncbase_TableExists_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableExists_ResponseParams_Versions) {
-		if syncbase_TableExists_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableExists_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadBool()
-		if err != nil {
-			return err
-		}
-		s.outExists = value0
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) TableExists(inName string) (outErr Error, outExists bool, err error) {
-	payload := &syncbase_TableExists_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_TableExists_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_TableExists_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_TableExists_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outExists = response.outExists
-	return
-}
-
-type syncbase_TableDeleteRowRange_Params struct {
-	inName  string
-	inStart []uint8
-	inLimit []uint8
-}
-
-func (s *syncbase_TableDeleteRowRange_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.inStart)), 8)
-	for _, elem0 := range s.inStart {
-		if err := encoder.WriteUint8(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.inLimit)), 8)
-	for _, elem0 := range s.inLimit {
-		if err := encoder.WriteUint8(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableDeleteRowRange_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_TableDeleteRowRange_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableDeleteRowRange_Params_Versions), func(i int) bool {
-		return syncbase_TableDeleteRowRange_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableDeleteRowRange_Params_Versions) {
-		if syncbase_TableDeleteRowRange_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableDeleteRowRange_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(8)
-			if err != nil {
-				return err
-			}
-			s.inStart = make([]uint8, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				value1, err := decoder.ReadUint8()
-				if err != nil {
-					return err
-				}
-				s.inStart[i0] = value1
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(8)
-			if err != nil {
-				return err
-			}
-			s.inLimit = make([]uint8, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				value1, err := decoder.ReadUint8()
-				if err != nil {
-					return err
-				}
-				s.inLimit[i0] = value1
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_TableDeleteRowRange_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_TableDeleteRowRange_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableDeleteRowRange_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_TableDeleteRowRange_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableDeleteRowRange_ResponseParams_Versions), func(i int) bool {
-		return syncbase_TableDeleteRowRange_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableDeleteRowRange_ResponseParams_Versions) {
-		if syncbase_TableDeleteRowRange_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableDeleteRowRange_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) TableDeleteRowRange(inName string, inStart []uint8, inLimit []uint8) (outErr Error, err error) {
-	payload := &syncbase_TableDeleteRowRange_Params{
-		inName,
-		inStart,
-		inLimit,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_TableDeleteRowRange_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_TableDeleteRowRange_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_TableDeleteRowRange_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_TableScan_Params struct {
-	inName  string
-	inStart []uint8
-	inLimit []uint8
-}
-
-func (s *syncbase_TableScan_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.inStart)), 8)
-	for _, elem0 := range s.inStart {
-		if err := encoder.WriteUint8(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.inLimit)), 8)
-	for _, elem0 := range s.inLimit {
-		if err := encoder.WriteUint8(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableScan_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_TableScan_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableScan_Params_Versions), func(i int) bool {
-		return syncbase_TableScan_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableScan_Params_Versions) {
-		if syncbase_TableScan_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableScan_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(8)
-			if err != nil {
-				return err
-			}
-			s.inStart = make([]uint8, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				value1, err := decoder.ReadUint8()
-				if err != nil {
-					return err
-				}
-				s.inStart[i0] = value1
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(8)
-			if err != nil {
-				return err
-			}
-			s.inLimit = make([]uint8, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				value1, err := decoder.ReadUint8()
-				if err != nil {
-					return err
-				}
-				s.inLimit[i0] = value1
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_TableScan_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_TableScan_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableScan_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_TableScan_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableScan_ResponseParams_Versions), func(i int) bool {
-		return syncbase_TableScan_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableScan_ResponseParams_Versions) {
-		if syncbase_TableScan_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableScan_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) TableScan(inName string, inStart []uint8, inLimit []uint8) (outErr Error, err error) {
-	payload := &syncbase_TableScan_Params{
-		inName,
-		inStart,
-		inLimit,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_TableScan_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_TableScan_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_TableScan_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_TableGetPermissions_Params struct {
-	inName string
-	inKey  string
-}
-
-func (s *syncbase_TableGetPermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inKey); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableGetPermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_TableGetPermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableGetPermissions_Params_Versions), func(i int) bool {
-		return syncbase_TableGetPermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableGetPermissions_Params_Versions) {
-		if syncbase_TableGetPermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableGetPermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inKey = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_TableGetPermissions_ResponseParams struct {
-	outErr      Error
-	outPermsArr []PrefixPerms
-}
-
-func (s *syncbase_TableGetPermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.outPermsArr)), 64)
-	for _, elem0 := range s.outPermsArr {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := elem0.Encode(encoder); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableGetPermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_TableGetPermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableGetPermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_TableGetPermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableGetPermissions_ResponseParams_Versions) {
-		if syncbase_TableGetPermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableGetPermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(64)
-			if err != nil {
-				return err
-			}
-			s.outPermsArr = make([]PrefixPerms, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				pointer1, err := decoder.ReadPointer()
-				if err != nil {
-					return err
-				}
-				if pointer1 == 0 {
-					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-				} else {
-					if err := s.outPermsArr[i0].Decode(decoder); err != nil {
-						return err
-					}
-				}
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) TableGetPermissions(inName string, inKey string) (outErr Error, outPermsArr []PrefixPerms, err error) {
-	payload := &syncbase_TableGetPermissions_Params{
-		inName,
-		inKey,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_TableGetPermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_TableGetPermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_TableGetPermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outPermsArr = response.outPermsArr
-	return
-}
-
-type syncbase_TableSetPermissions_Params struct {
-	inName   string
-	inPrefix string
-	inPerms  Perms
-}
-
-func (s *syncbase_TableSetPermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inPrefix); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.inPerms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableSetPermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *syncbase_TableSetPermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableSetPermissions_Params_Versions), func(i int) bool {
-		return syncbase_TableSetPermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableSetPermissions_Params_Versions) {
-		if syncbase_TableSetPermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableSetPermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inPrefix = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.inPerms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_TableSetPermissions_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_TableSetPermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableSetPermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_TableSetPermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableSetPermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_TableSetPermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableSetPermissions_ResponseParams_Versions) {
-		if syncbase_TableSetPermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableSetPermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) TableSetPermissions(inName string, inPrefix string, inPerms Perms) (outErr Error, err error) {
-	payload := &syncbase_TableSetPermissions_Params{
-		inName,
-		inPrefix,
-		inPerms,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_TableSetPermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_TableSetPermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_TableSetPermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_TableDeletePermissions_Params struct {
-	inName   string
-	inPrefix string
-}
-
-func (s *syncbase_TableDeletePermissions_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inPrefix); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableDeletePermissions_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_TableDeletePermissions_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableDeletePermissions_Params_Versions), func(i int) bool {
-		return syncbase_TableDeletePermissions_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableDeletePermissions_Params_Versions) {
-		if syncbase_TableDeletePermissions_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableDeletePermissions_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inPrefix = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_TableDeletePermissions_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_TableDeletePermissions_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_TableDeletePermissions_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_TableDeletePermissions_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_TableDeletePermissions_ResponseParams_Versions), func(i int) bool {
-		return syncbase_TableDeletePermissions_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_TableDeletePermissions_ResponseParams_Versions) {
-		if syncbase_TableDeletePermissions_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_TableDeletePermissions_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) TableDeletePermissions(inName string, inPrefix string) (outErr Error, err error) {
-	payload := &syncbase_TableDeletePermissions_Params{
-		inName,
-		inPrefix,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_TableDeletePermissions_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_TableDeletePermissions_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_TableDeletePermissions_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_RowExists_Params struct {
-	inName string
-}
-
-func (s *syncbase_RowExists_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_RowExists_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_RowExists_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_RowExists_Params_Versions), func(i int) bool {
-		return syncbase_RowExists_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_RowExists_Params_Versions) {
-		if syncbase_RowExists_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_RowExists_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_RowExists_ResponseParams struct {
-	outErr    Error
-	outExists bool
-}
-
-func (s *syncbase_RowExists_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WriteBool(s.outExists); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_RowExists_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_RowExists_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_RowExists_ResponseParams_Versions), func(i int) bool {
-		return syncbase_RowExists_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_RowExists_ResponseParams_Versions) {
-		if syncbase_RowExists_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_RowExists_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadBool()
-		if err != nil {
-			return err
-		}
-		s.outExists = value0
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) RowExists(inName string) (outErr Error, outExists bool, err error) {
-	payload := &syncbase_RowExists_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_RowExists_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_RowExists_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_RowExists_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outExists = response.outExists
-	return
-}
-
-type syncbase_RowGet_Params struct {
-	inName string
-}
-
-func (s *syncbase_RowGet_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_RowGet_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_RowGet_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_RowGet_Params_Versions), func(i int) bool {
-		return syncbase_RowGet_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_RowGet_Params_Versions) {
-		if syncbase_RowGet_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_RowGet_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_RowGet_ResponseParams struct {
-	outErr   Error
-	outValue []uint8
-}
-
-func (s *syncbase_RowGet_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.outValue)), 8)
-	for _, elem0 := range s.outValue {
-		if err := encoder.WriteUint8(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_RowGet_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_RowGet_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_RowGet_ResponseParams_Versions), func(i int) bool {
-		return syncbase_RowGet_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_RowGet_ResponseParams_Versions) {
-		if syncbase_RowGet_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_RowGet_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(8)
-			if err != nil {
-				return err
-			}
-			s.outValue = make([]uint8, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				value1, err := decoder.ReadUint8()
-				if err != nil {
-					return err
-				}
-				s.outValue[i0] = value1
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) RowGet(inName string) (outErr Error, outValue []uint8, err error) {
-	payload := &syncbase_RowGet_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_RowGet_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_RowGet_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_RowGet_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	outValue = response.outValue
-	return
-}
-
-type syncbase_RowPut_Params struct {
-	inName  string
-	inValue []uint8
-}
-
-func (s *syncbase_RowPut_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.inValue)), 8)
-	for _, elem0 := range s.inValue {
-		if err := encoder.WriteUint8(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_RowPut_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *syncbase_RowPut_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_RowPut_Params_Versions), func(i int) bool {
-		return syncbase_RowPut_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_RowPut_Params_Versions) {
-		if syncbase_RowPut_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_RowPut_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(8)
-			if err != nil {
-				return err
-			}
-			s.inValue = make([]uint8, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				value1, err := decoder.ReadUint8()
-				if err != nil {
-					return err
-				}
-				s.inValue[i0] = value1
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_RowPut_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_RowPut_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_RowPut_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_RowPut_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_RowPut_ResponseParams_Versions), func(i int) bool {
-		return syncbase_RowPut_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_RowPut_ResponseParams_Versions) {
-		if syncbase_RowPut_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_RowPut_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) RowPut(inName string, inValue []uint8) (outErr Error, err error) {
-	payload := &syncbase_RowPut_Params{
-		inName,
-		inValue,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_RowPut_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_RowPut_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_RowPut_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_RowDelete_Params struct {
-	inName string
-}
-
-func (s *syncbase_RowDelete_Params) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.inName); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_RowDelete_Params_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_RowDelete_Params) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_RowDelete_Params_Versions), func(i int) bool {
-		return syncbase_RowDelete_Params_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_RowDelete_Params_Versions) {
-		if syncbase_RowDelete_Params_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_RowDelete_Params_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.inName = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type syncbase_RowDelete_ResponseParams struct {
-	outErr Error
-}
-
-func (s *syncbase_RowDelete_ResponseParams) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.outErr.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncbase_RowDelete_ResponseParams_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *syncbase_RowDelete_ResponseParams) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncbase_RowDelete_ResponseParams_Versions), func(i int) bool {
-		return syncbase_RowDelete_ResponseParams_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncbase_RowDelete_ResponseParams_Versions) {
-		if syncbase_RowDelete_ResponseParams_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncbase_RowDelete_ResponseParams_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.outErr.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-func (p *Syncbase_Proxy) RowDelete(inName string) (outErr Error, err error) {
-	payload := &syncbase_RowDelete_Params{
-		inName,
-	}
-	header := bindings.MessageHeader{
-		Type:      syncbase_RowDelete_Name,
-		Flags:     bindings.MessageExpectsResponseFlag,
-		RequestId: p.ids.Count(),
-	}
-	var message *bindings.Message
-	if message, err = bindings.EncodeMessage(header, payload); err != nil {
-		err = fmt.Errorf("can't encode request: %v", err.Error())
-		p.Close_Proxy()
-		return
-	}
-	readResult := <-p.router.AcceptWithResponse(message)
-	if err = readResult.Error; err != nil {
-		p.Close_Proxy()
-		return
-	}
-	if readResult.Message.Header.Flags != bindings.MessageIsResponseFlag {
-		err = &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-			fmt.Sprintf("invalid message header flag: %v", readResult.Message.Header.Flags),
-		}
-		return
-	}
-	if got, want := readResult.Message.Header.Type, syncbase_RowDelete_Name; got != want {
-		err = &bindings.ValidationError{bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("invalid method in response: expected %v, got %v", want, got),
-		}
-		return
-	}
-	var response syncbase_RowDelete_ResponseParams
-	if err = readResult.Message.DecodePayload(&response); err != nil {
-		p.Close_Proxy()
-		return
-	}
-	outErr = response.outErr
-	return
-}
-
-type syncbase_Stub struct {
-	connector *bindings.Connector
-	impl      Syncbase
-}
-
-func NewSyncbaseStub(r Syncbase_Request, impl Syncbase, waiter bindings.AsyncWaiter) *bindings.Stub {
-	connector := bindings.NewConnector(r.PassMessagePipe(), waiter)
-	return bindings.NewStub(connector, &syncbase_Stub{connector, impl})
-}
-
-func (s *syncbase_Stub) Accept(message *bindings.Message) (err error) {
-	switch message.Header.Type {
-	case syncbase_ServiceGetPermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_ServiceGetPermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_ServiceGetPermissions_ResponseParams
-		response.outErr, response.outPerms, response.outVersion, err = s.impl.ServiceGetPermissions()
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_ServiceGetPermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_ServiceSetPermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_ServiceSetPermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_ServiceSetPermissions_ResponseParams
-		response.outErr, err = s.impl.ServiceSetPermissions(request.inPerms, request.inVersion)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_ServiceSetPermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_AppCreate_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_AppCreate_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_AppCreate_ResponseParams
-		response.outErr, err = s.impl.AppCreate(request.inName, request.inPerms)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_AppCreate_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_AppDelete_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_AppDelete_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_AppDelete_ResponseParams
-		response.outErr, err = s.impl.AppDelete(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_AppDelete_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_AppExists_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_AppExists_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_AppExists_ResponseParams
-		response.outErr, response.outExists, err = s.impl.AppExists(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_AppExists_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_AppGetPermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_AppGetPermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_AppGetPermissions_ResponseParams
-		response.outErr, response.outPerms, response.outVersion, err = s.impl.AppGetPermissions(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_AppGetPermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_AppSetPermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_AppSetPermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_AppSetPermissions_ResponseParams
-		response.outErr, err = s.impl.AppSetPermissions(request.inName, request.inPerms, request.inVersion)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_AppSetPermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbCreate_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbCreate_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbCreate_ResponseParams
-		response.outErr, err = s.impl.DbCreate(request.inName, request.inPerms)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbCreate_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbDelete_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbDelete_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbDelete_ResponseParams
-		response.outErr, err = s.impl.DbDelete(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbDelete_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbExists_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbExists_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbExists_ResponseParams
-		response.outErr, response.outExists, err = s.impl.DbExists(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbExists_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbExec_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbExec_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbExec_ResponseParams
-		response.outErr, err = s.impl.DbExec(request.inQuery)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbExec_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbBeginBatch_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbBeginBatch_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbBeginBatch_ResponseParams
-		response.outErr, response.outBatchDn, err = s.impl.DbBeginBatch(request.inName, request.inBo)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbBeginBatch_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbCommit_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbCommit_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbCommit_ResponseParams
-		response.outErr, err = s.impl.DbCommit(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbCommit_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbAbort_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbAbort_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbAbort_ResponseParams
-		response.outErr, err = s.impl.DbAbort(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbAbort_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbGetPermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbGetPermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbGetPermissions_ResponseParams
-		response.outErr, response.outPerms, response.outVersion, err = s.impl.DbGetPermissions(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbGetPermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbSetPermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbSetPermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbSetPermissions_ResponseParams
-		response.outErr, err = s.impl.DbSetPermissions(request.inName, request.inPerms, request.inVersion)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbSetPermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbGetSyncGroupNames_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbGetSyncGroupNames_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbGetSyncGroupNames_ResponseParams
-		response.outErr, response.outNames, err = s.impl.DbGetSyncGroupNames(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbGetSyncGroupNames_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbCreateSyncGroup_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbCreateSyncGroup_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbCreateSyncGroup_ResponseParams
-		response.outErr, err = s.impl.DbCreateSyncGroup(request.inName, request.inSgName, request.inSpec, request.inMyInfo)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbCreateSyncGroup_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbJoinSyncGroup_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbJoinSyncGroup_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbJoinSyncGroup_ResponseParams
-		response.outErr, err = s.impl.DbJoinSyncGroup(request.inName, request.inSgName, request.inMyInfo)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbJoinSyncGroup_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbLeaveSyncGroup_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbLeaveSyncGroup_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbLeaveSyncGroup_ResponseParams
-		response.outErr, err = s.impl.DbLeaveSyncGroup(request.inName, request.inSgName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbLeaveSyncGroup_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbDestroySyncGroup_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbDestroySyncGroup_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbDestroySyncGroup_ResponseParams
-		response.outErr, err = s.impl.DbDestroySyncGroup(request.inName, request.inSgName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbDestroySyncGroup_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbEjectFromSyncGroup_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbEjectFromSyncGroup_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbEjectFromSyncGroup_ResponseParams
-		response.outErr, err = s.impl.DbEjectFromSyncGroup(request.inName, request.inSgName, request.inMember)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbEjectFromSyncGroup_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbGetSyncGroupSpec_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbGetSyncGroupSpec_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbGetSyncGroupSpec_ResponseParams
-		response.outErr, response.outSpec, response.outVersion, err = s.impl.DbGetSyncGroupSpec(request.inName, request.inSgName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbGetSyncGroupSpec_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbSetSyncGroupSpec_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbSetSyncGroupSpec_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbSetSyncGroupSpec_ResponseParams
-		response.outErr, err = s.impl.DbSetSyncGroupSpec(request.inName, request.inSgName, request.inSpec, request.inVersion)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbSetSyncGroupSpec_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_DbGetSyncGroupMembers_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_DbGetSyncGroupMembers_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_DbGetSyncGroupMembers_ResponseParams
-		response.outErr, response.outInfos, err = s.impl.DbGetSyncGroupMembers(request.inName, request.inSgName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_DbGetSyncGroupMembers_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_TableCreate_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_TableCreate_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_TableCreate_ResponseParams
-		response.outErr, err = s.impl.TableCreate(request.inName, request.inPerms)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_TableCreate_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_TableDelete_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_TableDelete_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_TableDelete_ResponseParams
-		response.outErr, err = s.impl.TableDelete(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_TableDelete_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_TableExists_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_TableExists_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_TableExists_ResponseParams
-		response.outErr, response.outExists, err = s.impl.TableExists(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_TableExists_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_TableDeleteRowRange_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_TableDeleteRowRange_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_TableDeleteRowRange_ResponseParams
-		response.outErr, err = s.impl.TableDeleteRowRange(request.inName, request.inStart, request.inLimit)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_TableDeleteRowRange_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_TableScan_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_TableScan_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_TableScan_ResponseParams
-		response.outErr, err = s.impl.TableScan(request.inName, request.inStart, request.inLimit)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_TableScan_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_TableGetPermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_TableGetPermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_TableGetPermissions_ResponseParams
-		response.outErr, response.outPermsArr, err = s.impl.TableGetPermissions(request.inName, request.inKey)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_TableGetPermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_TableSetPermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_TableSetPermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_TableSetPermissions_ResponseParams
-		response.outErr, err = s.impl.TableSetPermissions(request.inName, request.inPrefix, request.inPerms)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_TableSetPermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_TableDeletePermissions_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_TableDeletePermissions_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_TableDeletePermissions_ResponseParams
-		response.outErr, err = s.impl.TableDeletePermissions(request.inName, request.inPrefix)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_TableDeletePermissions_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_RowExists_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_RowExists_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_RowExists_ResponseParams
-		response.outErr, response.outExists, err = s.impl.RowExists(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_RowExists_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_RowGet_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_RowGet_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_RowGet_ResponseParams
-		response.outErr, response.outValue, err = s.impl.RowGet(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_RowGet_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_RowPut_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_RowPut_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_RowPut_ResponseParams
-		response.outErr, err = s.impl.RowPut(request.inName, request.inValue)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_RowPut_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	case syncbase_RowDelete_Name:
-		if message.Header.Flags != bindings.MessageExpectsResponseFlag {
-			return &bindings.ValidationError{bindings.MessageHeaderInvalidFlags,
-				fmt.Sprintf("invalid message header flag: %v", message.Header.Flags),
-			}
-		}
-		var request syncbase_RowDelete_Params
-		if err := message.DecodePayload(&request); err != nil {
-			return err
-		}
-		var response syncbase_RowDelete_ResponseParams
-		response.outErr, err = s.impl.RowDelete(request.inName)
-		if err != nil {
-			return
-		}
-		header := bindings.MessageHeader{
-			Type:      syncbase_RowDelete_Name,
-			Flags:     bindings.MessageIsResponseFlag,
-			RequestId: message.Header.RequestId,
-		}
-		message, err = bindings.EncodeMessage(header, &response)
-		if err != nil {
-			return err
-		}
-		return s.connector.WriteMessage(message)
-	default:
-		return &bindings.ValidationError{
-			bindings.MessageHeaderUnknownMethod,
-			fmt.Sprintf("unknown method %v", message.Header.Type),
-		}
-	}
-	return
-}
-
-type Error struct {
-	Id         string
-	ActionCode uint32
-	Msg        string
-}
-
-func (s *Error) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(24, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.Id); err != nil {
-		return err
-	}
-	if err := encoder.WriteUint32(s.ActionCode); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.Msg); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var error_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{32, 0},
-}
-
-func (s *Error) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(error_Versions), func(i int) bool {
-		return error_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(error_Versions) {
-		if error_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := error_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.Id = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadUint32()
-		if err != nil {
-			return err
-		}
-		s.ActionCode = value0
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.Msg = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type Perms struct {
-	Json string
-}
-
-func (s *Perms) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.Json); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var perms_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *Perms) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(perms_Versions), func(i int) bool {
-		return perms_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(perms_Versions) {
-		if perms_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := perms_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.Json = value0
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type BatchOptions struct {
-	Hint     string
-	ReadOnly bool
-}
-
-func (s *BatchOptions) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.Hint); err != nil {
-		return err
-	}
-	if err := encoder.WriteBool(s.ReadOnly); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var batchOptions_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *BatchOptions) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(batchOptions_Versions), func(i int) bool {
-		return batchOptions_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(batchOptions_Versions) {
-		if batchOptions_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := batchOptions_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.Hint = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadBool()
-		if err != nil {
-			return err
-		}
-		s.ReadOnly = value0
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type PrefixPerms struct {
-	Prefix string
-	Perms  Perms
-}
-
-func (s *PrefixPerms) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(16, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.Prefix); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.Perms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var prefixPerms_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{24, 0},
-}
-
-func (s *PrefixPerms) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(prefixPerms_Versions), func(i int) bool {
-		return prefixPerms_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(prefixPerms_Versions) {
-		if prefixPerms_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := prefixPerms_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.Prefix = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.Perms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type SyncGroupSpec struct {
-	Description string
-	Perms       Perms
-	Prefixes    []string
-	MountTables []string
-	IsPrivate   bool
-}
-
-func (s *SyncGroupSpec) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(40, 0)
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := encoder.WriteString(s.Description); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	if err := s.Perms.Encode(encoder); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.Prefixes)), 64)
-	for _, elem0 := range s.Prefixes {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := encoder.WriteString(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.WritePointer(); err != nil {
-		return err
-	}
-	encoder.StartArray(uint32(len(s.MountTables)), 64)
-	for _, elem0 := range s.MountTables {
-		if err := encoder.WritePointer(); err != nil {
-			return err
-		}
-		if err := encoder.WriteString(elem0); err != nil {
-			return err
-		}
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	if err := encoder.WriteBool(s.IsPrivate); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncGroupSpec_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{48, 0},
-}
-
-func (s *SyncGroupSpec) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncGroupSpec_Versions), func(i int) bool {
-		return syncGroupSpec_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncGroupSpec_Versions) {
-		if syncGroupSpec_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncGroupSpec_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			value0, err := decoder.ReadString()
-			if err != nil {
-				return err
-			}
-			s.Description = value0
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			if err := s.Perms.Decode(decoder); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(64)
-			if err != nil {
-				return err
-			}
-			s.Prefixes = make([]string, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				pointer1, err := decoder.ReadPointer()
-				if err != nil {
-					return err
-				}
-				if pointer1 == 0 {
-					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-				} else {
-					value1, err := decoder.ReadString()
-					if err != nil {
-						return err
-					}
-					s.Prefixes[i0] = value1
-				}
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		pointer0, err := decoder.ReadPointer()
-		if err != nil {
-			return err
-		}
-		if pointer0 == 0 {
-			return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-		} else {
-			len0, err := decoder.StartArray(64)
-			if err != nil {
-				return err
-			}
-			s.MountTables = make([]string, len0)
-			for i0 := uint32(0); i0 < len0; i0++ {
-				pointer1, err := decoder.ReadPointer()
-				if err != nil {
-					return err
-				}
-				if pointer1 == 0 {
-					return &bindings.ValidationError{bindings.UnexpectedNullPointer, "unexpected null pointer"}
-				} else {
-					value1, err := decoder.ReadString()
-					if err != nil {
-						return err
-					}
-					s.MountTables[i0] = value1
-				}
-			}
-			if err := decoder.Finish(); err != nil {
-				return err
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadBool()
-		if err != nil {
-			return err
-		}
-		s.IsPrivate = value0
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-type SyncGroupMemberInfo struct {
-	SyncPriority uint8
-}
-
-func (s *SyncGroupMemberInfo) Encode(encoder *bindings.Encoder) error {
-	encoder.StartStruct(8, 0)
-	if err := encoder.WriteUint8(s.SyncPriority); err != nil {
-		return err
-	}
-	if err := encoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
-
-var syncGroupMemberInfo_Versions []bindings.DataHeader = []bindings.DataHeader{
-	bindings.DataHeader{16, 0},
-}
-
-func (s *SyncGroupMemberInfo) Decode(decoder *bindings.Decoder) error {
-	header, err := decoder.StartStruct()
-	if err != nil {
-		return err
-	}
-	index := sort.Search(len(syncGroupMemberInfo_Versions), func(i int) bool {
-		return syncGroupMemberInfo_Versions[i].ElementsOrVersion >= header.ElementsOrVersion
-	})
-	if index < len(syncGroupMemberInfo_Versions) {
-		if syncGroupMemberInfo_Versions[index].ElementsOrVersion > header.ElementsOrVersion {
-			index--
-		}
-		expectedSize := syncGroupMemberInfo_Versions[index].Size
-		if expectedSize != header.Size {
-			return &bindings.ValidationError{bindings.UnexpectedStructHeader,
-				fmt.Sprintf("invalid struct header size: should be %d, but was %d", expectedSize, header.Size),
-			}
-		}
-	}
-	if header.ElementsOrVersion >= 0 {
-		value0, err := decoder.ReadUint8()
-		if err != nil {
-			return err
-		}
-		s.SyncPriority = value0
-	}
-	if err := decoder.Finish(); err != nil {
-		return err
-	}
-	return nil
-}
diff --git a/gen/mojom/echo.mojom.dart b/gen/mojom/echo.mojom.dart
deleted file mode 120000
index ba586ca..0000000
--- a/gen/mojom/echo.mojom.dart
+++ /dev/null
@@ -1 +0,0 @@
-gen/dart-gen/mojom/lib/mojo/examples/echo.mojom.dart
\ No newline at end of file
diff --git a/gen/mojom/syncbase.mojom.dart b/gen/mojom/syncbase.mojom.dart
deleted file mode 120000
index 7239d2a..0000000
--- a/gen/mojom/syncbase.mojom.dart
+++ /dev/null
@@ -1 +0,0 @@
-gen/dart-gen/mojom/lib/mojo/syncbase/syncbase.mojom.dart
\ No newline at end of file
diff --git a/go/src/echo_client.go b/go/src/echo_client.go
new file mode 100644
index 0000000..13f0a43
--- /dev/null
+++ b/go/src/echo_client.go
@@ -0,0 +1,68 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// NOTE(nlacasse): This file was taken from $MOJO_DIR/src/examples/go.  The
+// only changes are the mojom import path, and the location of
+// echo_server.mojo.
+
+package main
+
+import (
+	"fmt"
+	"log"
+	"os"
+
+	"golang.org/x/mobile/app"
+
+	"mojo/public/go/application"
+	"mojo/public/go/bindings"
+	"mojo/public/go/system"
+
+	"mojom/echo"
+)
+
+//#include "mojo/public/c/system/types.h"
+import "C"
+
+type EchoClientDelegate struct{}
+
+func (delegate *EchoClientDelegate) Initialize(ctx application.Context) {
+	// TODO(nlacasse): Using a file:// url for the mojo service will not work
+	// on Android.  We should be using --map-origin flag, but that is not
+	// supported on Linux.  See https://github.com/domokit/mojo/issues/349
+	wd, err := os.Getwd()
+	if err != nil {
+		panic(err)
+	}
+	serverName := "file://" + wd + "/gen/mojo/echo_server.mojo"
+
+	echoRequest, echoPointer := echo.CreateMessagePipeForEcho()
+	ctx.ConnectToApplication(serverName).ConnectToService(&echoRequest)
+	echoProxy := echo.NewEchoProxy(echoPointer, bindings.GetAsyncWaiter())
+	response, err := echoProxy.EchoString(bindings.StringPointer("Hello, Gopher world!"))
+	if response != nil {
+		fmt.Printf("client: %s\n", *response)
+	} else {
+		log.Println(err)
+	}
+	echoProxy.Close_Proxy()
+	ctx.Close()
+}
+
+func (delegate *EchoClientDelegate) AcceptConnection(connection *application.Connection) {
+	connection.Close()
+}
+
+func (delegate *EchoClientDelegate) Quit() {
+}
+
+//export MojoMain
+func MojoMain(handle C.MojoHandle) C.MojoResult {
+	application.Run(&EchoClientDelegate{}, system.MojoHandle(handle))
+	return C.MOJO_RESULT_OK
+}
+
+func main() {
+	app.Run(app.Callbacks{})
+}
diff --git a/go/src/echo_server.go b/go/src/echo_server.go
new file mode 100644
index 0000000..892340a
--- /dev/null
+++ b/go/src/echo_server.go
@@ -0,0 +1,72 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// NOTE(nlacasse): This file was taken from $MOJO_DIR/src/examples/go.  The
+// only changes are the mojom import path.
+
+package main
+
+import (
+	"log"
+
+	"golang.org/x/mobile/app"
+
+	"mojo/public/go/application"
+	"mojo/public/go/bindings"
+	"mojo/public/go/system"
+
+	"mojom/echo"
+)
+
+//#include "mojo/public/c/system/types.h"
+import "C"
+
+type EchoImpl struct{}
+
+func (echo *EchoImpl) EchoString(inValue *string) (outValue *string, err error) {
+	log.Printf("server: %s\n", *inValue)
+	return inValue, nil
+}
+
+type EchoServerDelegate struct {
+	stubs []*bindings.Stub
+}
+
+func (delegate *EchoServerDelegate) Initialize(context application.Context) {}
+
+func (delegate *EchoServerDelegate) Create(request echo.Echo_Request) {
+	stub := echo.NewEchoStub(request, &EchoImpl{}, bindings.GetAsyncWaiter())
+	delegate.stubs = append(delegate.stubs, stub)
+	go func() {
+		for {
+			if err := stub.ServeRequest(); err != nil {
+				connectionError, ok := err.(*bindings.ConnectionError)
+				if !ok || !connectionError.Closed() {
+					log.Println(err)
+				}
+				break
+			}
+		}
+	}()
+}
+
+func (delegate *EchoServerDelegate) AcceptConnection(connection *application.Connection) {
+	connection.ProvideServices(&echo.Echo_ServiceFactory{delegate})
+}
+
+func (delegate *EchoServerDelegate) Quit() {
+	for _, stub := range delegate.stubs {
+		stub.Close()
+	}
+}
+
+//export MojoMain
+func MojoMain(handle C.MojoHandle) C.MojoResult {
+	application.Run(&EchoServerDelegate{}, system.MojoHandle(handle))
+	return C.MOJO_RESULT_OK
+}
+
+func main() {
+	app.Run(app.Callbacks{})
+}
diff --git a/mojom/echo.mojom b/mojom/echo.mojom
index 7604377..cd341d2 100644
--- a/mojom/echo.mojom
+++ b/mojom/echo.mojom
@@ -2,8 +2,8 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-[JavaPackage="org.chromium.mojo.examples.echo"]
-module mojo.examples;
+[JavaPackage="org.chromium.mojom.echo"]
+module mojo;
 
 interface Echo {
   EchoString(string? value) => (string? value);
