зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1293362 - Part 3: Add rust type information to the idl-parser for xpidl.py, r=froydnj
MozReview-Commit-ID: IPcuPuXDZho
This commit is contained in:
Родитель
94e3d3cb1b
Коммит
3fe123346a
|
@ -31,6 +31,19 @@ Interface members const/method/attribute conform to the following pattern:
|
|||
"""
|
||||
|
||||
|
||||
# XXX(nika): Fix the IDL files which do this so we can remove this list?
|
||||
def rustBlacklistedForward(s):
|
||||
"""These types are foward declared as interfaces, but never actually defined
|
||||
in IDL files. We don't want to generate references to them in rust for that
|
||||
reason."""
|
||||
blacklisted = [
|
||||
"nsIFrame",
|
||||
"nsIObjectFrame",
|
||||
"nsSubDocumentFrame",
|
||||
]
|
||||
return s in blacklisted
|
||||
|
||||
|
||||
def attlistToIDL(attlist):
|
||||
if len(attlist) == 0:
|
||||
return ''
|
||||
|
@ -102,23 +115,28 @@ class Builtin(object):
|
|||
kind = 'builtin'
|
||||
location = BuiltinLocation
|
||||
|
||||
def __init__(self, name, nativename, signed=False, maybeConst=False):
|
||||
def __init__(self, name, nativename, rustname, signed=False, maybeConst=False):
|
||||
self.name = name
|
||||
self.nativename = nativename
|
||||
self.rustname = rustname
|
||||
self.signed = signed
|
||||
self.maybeConst = maybeConst
|
||||
|
||||
def isScriptable(self):
|
||||
return True
|
||||
|
||||
def isPointer(self):
|
||||
"""Check if this type is a pointer type - this will control how pointers act"""
|
||||
return self.nativename.endswith('*')
|
||||
|
||||
def nativeType(self, calltype, shared=False, const=False):
|
||||
if const:
|
||||
print >>sys.stderr, IDLError("[const] doesn't make sense on builtin types.", self.location, warning=True)
|
||||
const = 'const '
|
||||
elif calltype == 'in' and self.nativename.endswith('*'):
|
||||
elif calltype == 'in' and self.isPointer():
|
||||
const = 'const '
|
||||
elif shared:
|
||||
if not self.nativename.endswith('*'):
|
||||
if not self.isPointer():
|
||||
raise IDLError("[shared] not applicable to non-pointer types.", self.location)
|
||||
const = 'const '
|
||||
else:
|
||||
|
@ -126,22 +144,32 @@ class Builtin(object):
|
|||
return "%s%s %s" % (const, self.nativename,
|
||||
calltype != 'in' and '*' or '')
|
||||
|
||||
def rustType(self, calltype, shared=False, const=False):
|
||||
# We want to rewrite any *mut pointers to *const pointers if constness
|
||||
# was requested.
|
||||
const = const or (calltype == 'in' and self.isPointer()) or shared
|
||||
rustname = self.rustname
|
||||
if const and self.isPointer():
|
||||
rustname = self.rustname.replace("*mut", "*const")
|
||||
|
||||
return "%s%s" % (calltype != 'in' and '*mut ' or '', rustname)
|
||||
|
||||
builtinNames = [
|
||||
Builtin('boolean', 'bool'),
|
||||
Builtin('void', 'void'),
|
||||
Builtin('octet', 'uint8_t'),
|
||||
Builtin('short', 'int16_t', True, True),
|
||||
Builtin('long', 'int32_t', True, True),
|
||||
Builtin('long long', 'int64_t', True, False),
|
||||
Builtin('unsigned short', 'uint16_t', False, True),
|
||||
Builtin('unsigned long', 'uint32_t', False, True),
|
||||
Builtin('unsigned long long', 'uint64_t', False, False),
|
||||
Builtin('float', 'float', True, False),
|
||||
Builtin('double', 'double', True, False),
|
||||
Builtin('char', 'char', True, False),
|
||||
Builtin('string', 'char *', False, False),
|
||||
Builtin('wchar', 'char16_t', False, False),
|
||||
Builtin('wstring', 'char16_t *', False, False),
|
||||
Builtin('boolean', 'bool', 'bool'),
|
||||
Builtin('void', 'void', 'libc::c_void'),
|
||||
Builtin('octet', 'uint8_t', 'libc::uint8_t'),
|
||||
Builtin('short', 'int16_t', 'libc::int16_t', True, True),
|
||||
Builtin('long', 'int32_t', 'libc::int32_t', True, True),
|
||||
Builtin('long long', 'int64_t', 'libc::int64_t', True, False),
|
||||
Builtin('unsigned short', 'uint16_t', 'libc::uint16_t', False, True),
|
||||
Builtin('unsigned long', 'uint32_t', 'libc::uint32_t', False, True),
|
||||
Builtin('unsigned long long', 'uint64_t', 'libc::uint64_t', False, False),
|
||||
Builtin('float', 'float', 'libc::c_float', True, False),
|
||||
Builtin('double', 'double', 'libc::c_double', True, False),
|
||||
Builtin('char', 'char', 'libc::c_char', True, False),
|
||||
Builtin('string', 'char *', '*const libc::c_char', False, False),
|
||||
Builtin('wchar', 'char16_t', 'libc::int16_t', False, False),
|
||||
Builtin('wstring', 'char16_t *', '*const libc::int16_t', False, False),
|
||||
]
|
||||
|
||||
builtinMap = {}
|
||||
|
@ -231,6 +259,15 @@ class NameMap(object):
|
|||
raise IDLError("Name '%s' not found", location)
|
||||
|
||||
|
||||
class RustNoncompat(Exception):
|
||||
"""Thie exception is raised when a particular type or function cannot be safely exposed to rust code"""
|
||||
def __init__(self, reason):
|
||||
self.reason = reason
|
||||
|
||||
def __str__(self):
|
||||
return self.reason
|
||||
|
||||
|
||||
class IDLError(Exception):
|
||||
def __init__(self, message, location, warning=False):
|
||||
self.message = message
|
||||
|
@ -355,6 +392,10 @@ class Typedef(object):
|
|||
return "%s %s" % (self.name,
|
||||
calltype != 'in' and '*' or '')
|
||||
|
||||
def rustType(self, calltype):
|
||||
return "%s%s" % (calltype != 'in' and '*mut ' or '',
|
||||
self.name)
|
||||
|
||||
def __str__(self):
|
||||
return "typedef %s %s\n" % (self.type, self.name)
|
||||
|
||||
|
@ -391,6 +432,12 @@ class Forward(object):
|
|||
return "%s %s" % (self.name,
|
||||
calltype != 'in' and '* *' or '*')
|
||||
|
||||
def rustType(self, calltype):
|
||||
if rustBlacklistedForward(self.name):
|
||||
raise RustNoncompat("forward declaration %s is unsupported" % self.name)
|
||||
return "%s*const %s" % (calltype != 'in' and '*mut ' or '',
|
||||
self.name)
|
||||
|
||||
def __str__(self):
|
||||
return "forward-declared %s\n" % self.name
|
||||
|
||||
|
@ -410,6 +457,19 @@ class Native(object):
|
|||
'jsval': 'JS::Value'
|
||||
}
|
||||
|
||||
# Mappings from C++ native name types to rust native names. Types which
|
||||
# aren't listed here are incompatible with rust code.
|
||||
rust_nativenames = {
|
||||
'void': "libc::c_void",
|
||||
'char': "u8",
|
||||
'char16_t': "u16",
|
||||
'nsID': "nsID",
|
||||
'nsIID': "nsIID",
|
||||
'nsCID': "nsCID",
|
||||
'nsAString': "::nsstring::nsAString",
|
||||
'nsACString': "::nsstring::nsACString",
|
||||
}
|
||||
|
||||
def __init__(self, name, nativename, attlist, location):
|
||||
self.name = name
|
||||
self.nativename = nativename
|
||||
|
@ -477,6 +537,29 @@ class Native(object):
|
|||
m = calltype != 'in' and '*' or ''
|
||||
return "%s%s %s" % (const and 'const ' or '', self.nativename, m)
|
||||
|
||||
def rustType(self, calltype, const=False, shared=False):
|
||||
if shared:
|
||||
if calltype != 'out':
|
||||
raise IDLError("[shared] only applies to out parameters.")
|
||||
const = True
|
||||
|
||||
if self.specialtype is not None and calltype == 'in':
|
||||
const = True
|
||||
|
||||
if self.nativename not in self.rust_nativenames:
|
||||
raise RustNoncompat("native type %s is unsupported" % self.nativename)
|
||||
name = self.rust_nativenames[self.nativename]
|
||||
|
||||
if self.isRef(calltype):
|
||||
m = const and '&' or '&mut '
|
||||
elif self.isPtr(calltype):
|
||||
m = (const and '*const ' or '*mut ')
|
||||
if self.modifier == 'ptr' and calltype != 'in':
|
||||
m += '*mut '
|
||||
else:
|
||||
m = calltype != 'in' and '*mut ' or ''
|
||||
return "%s%s" % (m, name)
|
||||
|
||||
def __str__(self):
|
||||
return "native %s(%s)\n" % (self.name, self.nativename)
|
||||
|
||||
|
@ -555,6 +638,10 @@ class Interface(object):
|
|||
self.name,
|
||||
calltype != 'in' and '* *' or '*')
|
||||
|
||||
def rustType(self, calltype):
|
||||
return "%s*const %s" % (calltype != 'in' and '*mut ' or '',
|
||||
self.name)
|
||||
|
||||
def __str__(self):
|
||||
l = ["interface %s\n" % self.name]
|
||||
if self.base is not None:
|
||||
|
@ -1002,6 +1089,20 @@ class Param(object):
|
|||
except TypeError, e:
|
||||
raise IDLError("Unexpected parameter attribute", self.location)
|
||||
|
||||
def rustType(self):
|
||||
kwargs = {}
|
||||
if self.shared:
|
||||
kwargs['shared'] = True
|
||||
if self.const:
|
||||
kwargs['const'] = True
|
||||
|
||||
try:
|
||||
return self.realtype.rustType(self.paramtype, **kwargs)
|
||||
except IDLError, e:
|
||||
raise IDLError(e.message, self.location)
|
||||
except TypeError, e:
|
||||
raise IDLError("Unexpected parameter attribute", self.location)
|
||||
|
||||
def toIDL(self):
|
||||
return "%s%s %s %s" % (paramAttlistToIDL(self.attlist),
|
||||
self.paramtype,
|
||||
|
@ -1020,6 +1121,10 @@ class Array(object):
|
|||
return "%s%s*" % (const and 'const ' or '',
|
||||
self.type.nativeType(calltype))
|
||||
|
||||
def rustType(self, calltype, const=False):
|
||||
return "%s %s" % (const and '*const' or '*mut',
|
||||
self.type.rustType(calltype))
|
||||
|
||||
|
||||
class IDLParser(object):
|
||||
keywords = {
|
||||
|
|
Загрузка…
Ссылка в новой задаче