protocol: add the "bitmask" enum type and check for it

Plus check for duplicate values in enums
This commit is contained in:
Peter Hutterer 2023-02-08 13:17:47 +10:00
parent bde838fd1d
commit 21df02e499
2 changed files with 36 additions and 7 deletions

View file

@ -311,7 +311,7 @@
</description>
</request>
<enum name="capabilities" since="1">
<enum name="capabilities" since="1" type="bitmask">
<description summary="Seat capabilities">
A set of capabilities possible available on this seat. A client may bind to these
capabilies and an EIS implementation may then create device based on the bound
@ -417,7 +417,7 @@
<arg name="name" type="string" help="the device name"/>
</event>
<enum name="capabilities" since="1">
<enum name="capabilities" since="1" type="bitmask">
<entry name="pointer" value="2"/>
<entry name="pointer_absolute" value="4"/>
<entry name="keyboard" value="8"/>

View file

@ -183,14 +183,27 @@ class Enum:
name: str = attr.ib()
since: int = attr.ib()
interface: "Interface" = attr.ib()
is_bitmask: bool = attr.ib(default=False)
entries: list[Entry] = attr.ib(init=False, factory=list)
@classmethod
def create(cls, name: str, interface: "Interface", since: int = 1) -> "Enum":
return cls(name=name, since=since, interface=interface)
def create(
cls, name: str, interface: "Interface", since: int = 1, is_bitmask: bool = False
) -> "Enum":
return cls(name=name, since=since, interface=interface, is_bitmask=is_bitmask)
def add_entry(self, entry: Entry) -> None:
for e in self.entries:
if e.value == entry.value:
raise ValueError(f"Duplicate enum value {entry.value}")
if self.is_bitmask:
if e.value < 0:
raise ValueError("Bitmasks must not be less than zero")
if e.value.bit_count() > 1:
raise ValueError("Bitmasks must have exactly one bit set")
self.entries.append(entry)
@property
@ -376,7 +389,20 @@ class Protocol(xml.sax.handler.ContentHandler):
*self.location, f"Missing attribute {e} in element '{element}'"
)
enum = Enum.create(name=name, since=since, interface=self.current_interface)
enum_type = attrs.get("type", None)
if enum_type is not None and enum_type not in ["bitmask"]:
raise XmlError(
*self.location,
f"Invalid enum type {enum_type} in element '{element}'",
)
is_bitmask = enum_type == "bitmask"
enum = Enum.create(
name=name,
since=since,
interface=self.current_interface,
is_bitmask=is_bitmask,
)
self.current_interface.add_enum(enum)
self.current_message = enum
elif element == "arg":
@ -414,10 +440,13 @@ class Protocol(xml.sax.handler.ContentHandler):
*self.location, f"Invalid element '{element}' must be inside <enum>"
)
name = attrs["name"]
value = attrs["value"]
value = int(attrs["value"])
summary = attrs.get("summary", "")
entry = Entry.create(name=name, value=value, summary=summary)
self.current_message.add_entry(entry)
try:
self.current_message.add_entry(entry)
except ValueError as e:
raise XmlError(*self.location, str(e))
def endElement(self, name):
if name == "interface":