зеркало из 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):
|
def attlistToIDL(attlist):
|
||||||
if len(attlist) == 0:
|
if len(attlist) == 0:
|
||||||
return ''
|
return ''
|
||||||
|
@ -102,23 +115,28 @@ class Builtin(object):
|
||||||
kind = 'builtin'
|
kind = 'builtin'
|
||||||
location = BuiltinLocation
|
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.name = name
|
||||||
self.nativename = nativename
|
self.nativename = nativename
|
||||||
|
self.rustname = rustname
|
||||||
self.signed = signed
|
self.signed = signed
|
||||||
self.maybeConst = maybeConst
|
self.maybeConst = maybeConst
|
||||||
|
|
||||||
def isScriptable(self):
|
def isScriptable(self):
|
||||||
return True
|
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):
|
def nativeType(self, calltype, shared=False, const=False):
|
||||||
if const:
|
if const:
|
||||||
print >>sys.stderr, IDLError("[const] doesn't make sense on builtin types.", self.location, warning=True)
|
print >>sys.stderr, IDLError("[const] doesn't make sense on builtin types.", self.location, warning=True)
|
||||||
const = 'const '
|
const = 'const '
|
||||||
elif calltype == 'in' and self.nativename.endswith('*'):
|
elif calltype == 'in' and self.isPointer():
|
||||||
const = 'const '
|
const = 'const '
|
||||||
elif shared:
|
elif shared:
|
||||||
if not self.nativename.endswith('*'):
|
if not self.isPointer():
|
||||||
raise IDLError("[shared] not applicable to non-pointer types.", self.location)
|
raise IDLError("[shared] not applicable to non-pointer types.", self.location)
|
||||||
const = 'const '
|
const = 'const '
|
||||||
else:
|
else:
|
||||||
|
@ -126,22 +144,32 @@ class Builtin(object):
|
||||||
return "%s%s %s" % (const, self.nativename,
|
return "%s%s %s" % (const, self.nativename,
|
||||||
calltype != 'in' and '*' or '')
|
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 = [
|
builtinNames = [
|
||||||
Builtin('boolean', 'bool'),
|
Builtin('boolean', 'bool', 'bool'),
|
||||||
Builtin('void', 'void'),
|
Builtin('void', 'void', 'libc::c_void'),
|
||||||
Builtin('octet', 'uint8_t'),
|
Builtin('octet', 'uint8_t', 'libc::uint8_t'),
|
||||||
Builtin('short', 'int16_t', True, True),
|
Builtin('short', 'int16_t', 'libc::int16_t', True, True),
|
||||||
Builtin('long', 'int32_t', True, True),
|
Builtin('long', 'int32_t', 'libc::int32_t', True, True),
|
||||||
Builtin('long long', 'int64_t', True, False),
|
Builtin('long long', 'int64_t', 'libc::int64_t', True, False),
|
||||||
Builtin('unsigned short', 'uint16_t', False, True),
|
Builtin('unsigned short', 'uint16_t', 'libc::uint16_t', False, True),
|
||||||
Builtin('unsigned long', 'uint32_t', False, True),
|
Builtin('unsigned long', 'uint32_t', 'libc::uint32_t', False, True),
|
||||||
Builtin('unsigned long long', 'uint64_t', False, False),
|
Builtin('unsigned long long', 'uint64_t', 'libc::uint64_t', False, False),
|
||||||
Builtin('float', 'float', True, False),
|
Builtin('float', 'float', 'libc::c_float', True, False),
|
||||||
Builtin('double', 'double', True, False),
|
Builtin('double', 'double', 'libc::c_double', True, False),
|
||||||
Builtin('char', 'char', True, False),
|
Builtin('char', 'char', 'libc::c_char', True, False),
|
||||||
Builtin('string', 'char *', False, False),
|
Builtin('string', 'char *', '*const libc::c_char', False, False),
|
||||||
Builtin('wchar', 'char16_t', False, False),
|
Builtin('wchar', 'char16_t', 'libc::int16_t', False, False),
|
||||||
Builtin('wstring', 'char16_t *', False, False),
|
Builtin('wstring', 'char16_t *', '*const libc::int16_t', False, False),
|
||||||
]
|
]
|
||||||
|
|
||||||
builtinMap = {}
|
builtinMap = {}
|
||||||
|
@ -231,6 +259,15 @@ class NameMap(object):
|
||||||
raise IDLError("Name '%s' not found", location)
|
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):
|
class IDLError(Exception):
|
||||||
def __init__(self, message, location, warning=False):
|
def __init__(self, message, location, warning=False):
|
||||||
self.message = message
|
self.message = message
|
||||||
|
@ -355,6 +392,10 @@ class Typedef(object):
|
||||||
return "%s %s" % (self.name,
|
return "%s %s" % (self.name,
|
||||||
calltype != 'in' and '*' or '')
|
calltype != 'in' and '*' or '')
|
||||||
|
|
||||||
|
def rustType(self, calltype):
|
||||||
|
return "%s%s" % (calltype != 'in' and '*mut ' or '',
|
||||||
|
self.name)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return "typedef %s %s\n" % (self.type, self.name)
|
return "typedef %s %s\n" % (self.type, self.name)
|
||||||
|
|
||||||
|
@ -391,6 +432,12 @@ class Forward(object):
|
||||||
return "%s %s" % (self.name,
|
return "%s %s" % (self.name,
|
||||||
calltype != 'in' and '* *' or '*')
|
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):
|
def __str__(self):
|
||||||
return "forward-declared %s\n" % self.name
|
return "forward-declared %s\n" % self.name
|
||||||
|
|
||||||
|
@ -410,6 +457,19 @@ class Native(object):
|
||||||
'jsval': 'JS::Value'
|
'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):
|
def __init__(self, name, nativename, attlist, location):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.nativename = nativename
|
self.nativename = nativename
|
||||||
|
@ -477,6 +537,29 @@ class Native(object):
|
||||||
m = calltype != 'in' and '*' or ''
|
m = calltype != 'in' and '*' or ''
|
||||||
return "%s%s %s" % (const and 'const ' or '', self.nativename, m)
|
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):
|
def __str__(self):
|
||||||
return "native %s(%s)\n" % (self.name, self.nativename)
|
return "native %s(%s)\n" % (self.name, self.nativename)
|
||||||
|
|
||||||
|
@ -555,6 +638,10 @@ class Interface(object):
|
||||||
self.name,
|
self.name,
|
||||||
calltype != 'in' and '* *' or '*')
|
calltype != 'in' and '* *' or '*')
|
||||||
|
|
||||||
|
def rustType(self, calltype):
|
||||||
|
return "%s*const %s" % (calltype != 'in' and '*mut ' or '',
|
||||||
|
self.name)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
l = ["interface %s\n" % self.name]
|
l = ["interface %s\n" % self.name]
|
||||||
if self.base is not None:
|
if self.base is not None:
|
||||||
|
@ -1002,6 +1089,20 @@ class Param(object):
|
||||||
except TypeError, e:
|
except TypeError, e:
|
||||||
raise IDLError("Unexpected parameter attribute", self.location)
|
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):
|
def toIDL(self):
|
||||||
return "%s%s %s %s" % (paramAttlistToIDL(self.attlist),
|
return "%s%s %s %s" % (paramAttlistToIDL(self.attlist),
|
||||||
self.paramtype,
|
self.paramtype,
|
||||||
|
@ -1020,6 +1121,10 @@ class Array(object):
|
||||||
return "%s%s*" % (const and 'const ' or '',
|
return "%s%s*" % (const and 'const ' or '',
|
||||||
self.type.nativeType(calltype))
|
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):
|
class IDLParser(object):
|
||||||
keywords = {
|
keywords = {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче