Bug 1530467 - Add Array<T> support to xpcom rust bindings, r=froydnj
authorNika Layzell <nika@thelayzells.com>
Tue, 26 Feb 2019 20:51:19 +0000
changeset 519428 2f27f2c7a443b3c798c0722379328e6ba6c3ef5d
parent 519427 a836b30ac0705082c7156307a3e54248507851f9
child 519429 c2091f595c72666fdc160828a3577aac7974f1ba
push id10862
push userffxbld-merge
push dateMon, 11 Mar 2019 13:01:11 +0000
treeherdermozilla-beta@a2e7f5c935da [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersfroydnj
bugs1530467
milestone67.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1530467 - Add Array<T> support to xpcom rust bindings, r=froydnj Differential Revision: https://phabricator.services.mozilla.com/D21046
Cargo.lock
xpcom/idl-parser/xpidl/xpidl.py
xpcom/rust/xpcom/Cargo.toml
xpcom/rust/xpcom/src/lib.rs
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3239,16 +3239,17 @@ source = "registry+https://github.com/ru
 
 [[package]]
 name = "xpcom"
 version = "0.1.0"
 dependencies = [
  "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)",
  "nserror 0.1.0",
  "nsstring 0.1.0",
+ "thin-vec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "threadbound 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "xpcom_macros 0.1.0",
 ]
 
 [[package]]
 name = "xpcom-gtest"
 version = "0.1.0"
 dependencies = [
--- a/xpcom/idl-parser/xpidl/xpidl.py
+++ b/xpcom/idl-parser/xpidl/xpidl.py
@@ -418,20 +418,19 @@ class Typedef(object):
     def isScriptable(self):
         return self.realtype.isScriptable()
 
     def nativeType(self, calltype):
         return "%s %s" % (self.name, '*' if 'out' in calltype else '')
 
     def rustType(self, calltype):
         if self.name == 'nsresult':
-            return "%s::nserror::nsresult" % (calltype != 'in' and '*mut ' or '')
+            return "%s::nserror::nsresult" % ('*mut ' if 'out' in calltype else '')
 
-        return "%s%s" % (calltype != 'in' and '*mut ' or '',
-                         self.name)
+        return "%s%s" % ('*mut ' if 'out' in calltype else '', self.name)
 
     def __str__(self):
         return "typedef %s %s\n" % (self.type, self.name)
 
 
 class Forward(object):
     kind = 'forward'
 
@@ -463,16 +462,18 @@ class Forward(object):
     def nativeType(self, calltype):
         if calltype == 'element':
             return 'RefPtr<%s>' % self.name
         return "%s *%s" % (self.name, '*' if 'out' in calltype else '')
 
     def rustType(self, calltype):
         if rustBlacklistedForward(self.name):
             raise RustNoncompat("forward declaration %s is unsupported" % self.name)
+        if calltype == 'element':
+            return 'RefPtr<%s>' % self.name
         return "%s*const %s" % (calltype != 'in' and '*mut ' or '',
                                 self.name)
 
     def __str__(self):
         return "forward-declared %s\n" % self.name
 
 
 class Native(object):
@@ -594,16 +595,21 @@ class Native(object):
         if self.modifier not in ['ptr', 'ref']:
             raise RustNoncompat('Rust only supports [ref] / [ptr] native types')
 
         prefix = '*mut ' if 'out' in calltype else '*const '
         if 'out' in calltype and self.modifier == 'ptr':
             prefix += '*mut '
 
         if self.specialtype == 'nsid':
+            if 'element' in calltype:
+                if self.isPtr(calltype):
+                    raise IDLError("Array<nsIDPtr> not yet supported. "
+                                   "File an XPConnect bug if you need it.", self.location)
+                return self.nativename
             return prefix + self.nativename
         if self.specialtype in ['cstring', 'utf8string']:
             if 'element' in calltype:
                 return '::nsstring::nsCString'
             return prefix + '::nsstring::nsACString'
         if self.specialtype == 'astring':
             if 'element' in calltype:
                 return '::nsstring::nsString'
@@ -757,16 +763,18 @@ class Interface(object):
 
     def nativeType(self, calltype, const=False):
         if calltype == 'element':
             return 'RefPtr<%s>' % self.name
         return "%s%s *%s" % ('const ' if const else '', self.name,
                              '*' if 'out' in calltype else '')
 
     def rustType(self, calltype, const=False):
+        if calltype == 'element':
+            return 'RefPtr<%s>' % self.name
         return "%s*const %s" % ('*mut ' if 'out' in calltype else '',
                                 self.name)
 
     def __str__(self):
         l = ["interface %s\n" % self.name]
         if self.base is not None:
             l.append("\tbase %s\n" % self.base)
         l.append(str(self.attributes))
@@ -1326,19 +1334,26 @@ class Array(object):
         if 'out' in calltype:
             return '%s& ' % base
         elif 'in' == calltype:
             return 'const %s& ' % base
         else:
             return base
 
     def rustType(self, calltype):
-        # NOTE: To add Rust support, ensure 'element' is handled correctly in
-        # all rustType callees.
-        raise RustNoncompat("Array<...> types")
+        if calltype == 'legacyelement':
+            raise IDLError("[array] Array<T> is unsupported", self.location)
+
+        base = 'thin_vec::ThinVec<%s>' % self.type.rustType('element')
+        if 'out' in calltype:
+            return '*mut %s' % base
+        elif 'in' == calltype:
+            return '*const %s' % base
+        else:
+            return base
 
 
 TypeId = namedtuple('TypeId', 'name params')
 
 
 # Make str(TypeId) produce a nicer value
 TypeId.__str__ = lambda self: \
     "%s<%s>" % (self.name, ', '.join(str(p) for p in self.params)) \
--- a/xpcom/rust/xpcom/Cargo.toml
+++ b/xpcom/rust/xpcom/Cargo.toml
@@ -4,8 +4,9 @@ version = "0.1.0"
 authors = ["michael@thelayzells.com"]
 
 [dependencies]
 libc = "0.2"
 nsstring = { path = "../nsstring" }
 nserror = { path = "../nserror" }
 threadbound = "0.1"
 xpcom_macros = { path = "xpcom_macros" }
+thin-vec = { version = "0.1.0", features = ["gecko-ffi"] }
--- a/xpcom/rust/xpcom/src/lib.rs
+++ b/xpcom/rust/xpcom/src/lib.rs
@@ -10,16 +10,17 @@
 
 #![allow(non_snake_case)]
 #![allow(non_camel_case_types)]
 
 extern crate libc;
 extern crate nsstring;
 extern crate nserror;
 extern crate threadbound;
+extern crate thin_vec;
 
 // re-export the xpcom_macros macro
 #[macro_use]
 #[allow(unused_imports)]
 extern crate xpcom_macros;
 #[doc(hidden)]
 pub use xpcom_macros::*;