__all__ = [
'DVTargetDevice',
]
import struct
from typing import Optional
from ._helpers import BytesReader
from .dev_mode_a import DevModeA
class DVTargetDevice:
"""
Specifies information about a device that renders the presentation data.
The creator of this data structure MUST NOT assume that it will be
understood during processing.
"""
def __init__(self, data: Optional[bytes]):
self.__driverName = None
self.__deviceName = None
self.__portName = None
self.__extDevMode = None
if not data:
return
reader = BytesReader(data)
# We have 4 fields to read, and *technically* they may not all even be
# present, given that this structure can be 4 bytes? Reading all of
# these is also much more complicated than other structures, as they can
# technically overlap. We are just going to be *much* more lenient about
# this structure.
offset1 = offset2 = offset3 = offset4 = -1
try:
offset1 = reader.readUnsignedShort()
offset2 = reader.readUnsignedShort()
offset3 = reader.readUnsignedShort()
offset4 = reader.readUnsignedShort()
except IOError:
pass
if offset1 != -1 and offset1 < len(data):
reader.seek(offset1)
try:
self.__driverName = reader.readByteString()
except IOError:
self.__driverName = reader.read()
if not self.__driverName:
self.__driverName = None
if offset2 != -1 and offset2 < len(data):
reader.seek(offset2)
try:
self.__deviceName = reader.readByteString()
except IOError:
self.__deviceName = reader.read()
if not self.__deviceName:
self.__deviceName = None
if offset3 != -1 and offset3 < len(data):
reader.seek(offset3)
try:
self.__portName = reader.readByteString()
except IOError:
self.__portName = reader.read()
if not self.__portName:
self.__portName = None
if offset4 != -1 and offset4 < len(data):
reader.seek(offset4)
try:
devmode = DevModeA(reader.read(56))
if devmode:
self.__extDevMode = devmode
except IOError:
self.__extDevMode = None
def __bytes__(self) -> bytes:
ret = self.toBytes()
if not isinstance(ret, bytes):
raise TypeError(f'Cannot convert {self.__class__.__name__} instance to bytes.')
return ret
def toBytes(self) -> Optional[bytes]:
if not (self.driverName or self.deviceName or self.portName or self.extDevMode):
return None
currentPosition = 8
offset1 = 8 if self.__driverName else 0
if self.__driverName:
currentPosition += len(self.__driverName) + 1
offset2 = currentPosition if self.__deviceName else 0
if self.__deviceName:
currentPosition += len(self.__deviceName) + 1
offset3 = currentPosition if self.__portName else 0
if self.__portName:
currentPosition += len(self.__portName) + 1
extDevModeBytes = bytes(self.__extDevMode) if self.__extDevMode else None
offset4 = currentPosition if extDevModeBytes else 0
try:
ret = struct.pack('<HHHH', offset1, offset2, offset3, offset4)
except struct.error:
raise ValueError('DVTargetDevice structure contains too much data.')
if self.__driverName:
ret += self.__driverName + b'\x00'
if self.__deviceName:
ret += self.__deviceName + b'\x00'
if self.__portName:
ret += self.__portName + b'\x00'
if extDevModeBytes:
ret += extDevModeBytes
return ret
@property
def driverName(self) -> Optional[bytes]:
"""
Optional ANSI string that contains a hunt on how to display or print
presentation data.
"""
return self.__driverName
@driverName.setter
def driverName(self, data: Optional[bytes]) -> None:
self.__driverName = None if not data else data
@property
def deviceName(self) -> Optional[bytes]:
"""
Optional ANSI string that contains a hunt on how to display or print
presentation data.
"""
return self.__deviceName
@deviceName.setter
def deviceName(self, data: Optional[bytes]) -> None:
self.__deviceName = None if not data else data
@property
def portName(self) -> Optional[bytes]:
"""
Optional ANSI string that contains any arbitrary value.
"""
return self.__portName
@portName.setter
def portName(self, data: Optional[bytes]) -> None:
self.__portName = None if not data else data
@property
def extDevMode(self) -> Optional[DevModeA]:
"""
Optional ANSI string that contains a hunt on how to display or print
presentation data.
"""
return self.__extDevMode
@extDevMode.setter
def extDevMode(self, data: Optional[DevModeA]) -> None:
self.__extDevMode = None if not data else data