PyLibMS 5.0.2__py3-none-any.whl → 5.0.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lms/common/field/io.py +80 -80
- lms/common/field/lms_datatype.py +152 -152
- lms/common/field/lms_field.py +183 -183
- lms/common/lms_constants.py +12 -12
- lms/common/lms_exceptions.py +13 -13
- lms/common/lms_fileinfo.py +11 -11
- lms/common/stream/fileinfo.py +80 -80
- lms/common/stream/hashtable.py +88 -88
- lms/common/stream/section.py +57 -57
- lms/fileio/encoding.py +42 -42
- lms/fileio/io.py +198 -198
- lms/flowchart/definitions/lms_nodeexceptions.py +7 -7
- lms/flowchart/definitions/node.py +632 -632
- lms/flowchart/definitions/node_type.py +130 -130
- lms/flowchart/flw3.py +421 -421
- lms/flowchart/msbf.py +208 -208
- lms/flowchart/msbfio.py +139 -139
- lms/message/lms_messagetext.py +184 -184
- lms/message/msbt.py +271 -271
- lms/message/msbtentry.py +103 -103
- lms/message/msbtio.py +246 -246
- lms/message/section/atr1.py +115 -115
- lms/message/section/nli1.py +22 -22
- lms/message/section/tsy1.py +13 -13
- lms/message/section/txt2.py +67 -67
- lms/message/tag/io/param_io.py +91 -91
- lms/message/tag/io/tag_io.py +115 -115
- lms/message/tag/lms_tag.py +236 -236
- lms/message/tag/lms_tagexceptions.py +10 -10
- lms/project/definitions/attribute.py +32 -32
- lms/project/definitions/color.py +10 -10
- lms/project/definitions/style.py +10 -10
- lms/project/definitions/tag.py +137 -137
- lms/project/msbp.py +71 -71
- lms/project/msbpread.py +111 -111
- lms/project/section/ali2.py +22 -22
- lms/project/section/ati2.py +17 -17
- lms/project/section/clr1.py +15 -15
- lms/project/section/string.py +16 -16
- lms/project/section/syl3.py +17 -17
- lms/project/section/tag2.py +20 -20
- lms/project/section/tgg2.py +24 -24
- lms/project/section/tgp2.py +30 -30
- lms/titleconfig/config.py +301 -301
- lms/titleconfig/definitions/attribute.py +28 -28
- lms/titleconfig/definitions/field.py +32 -32
- lms/titleconfig/definitions/nodes.py +151 -151
- lms/titleconfig/definitions/tags.py +90 -90
- {pylibms-5.0.2.dist-info → pylibms-5.0.4.dist-info}/METADATA +118 -117
- pylibms-5.0.4.dist-info/RECORD +67 -0
- {pylibms-5.0.2.dist-info → pylibms-5.0.4.dist-info}/licenses/LICENSE +6 -6
- lms/titleconfig/presets/Badge Arcade.yaml +0 -430
- lms/titleconfig/presets/Brain Age Concentration Training.yaml +0 -132
- lms/titleconfig/presets/Kirby Planet Robobot.yaml +0 -209
- lms/titleconfig/presets/Super Mario 3D Land.yaml +0 -367
- lms/titleconfig/presets/Super Mario 3D World + Bowsers Fury.yaml +0 -200
- lms/titleconfig/presets/Super Mario Odyssey.yaml +0 -1961
- lms/titleconfig/presets/The Legend of Zelda Echos of Wisdom.yaml +0 -110
- lms/titleconfig/presets/The Legend of Zelda a Link Between Worlds.yaml +0 -383
- lms/titleconfig/presets/Tomodachi Life Living The Dream.yaml +0 -3369
- pylibms-5.0.2.dist-info/RECORD +0 -76
- {pylibms-5.0.2.dist-info → pylibms-5.0.4.dist-info}/WHEEL +0 -0
- {pylibms-5.0.2.dist-info → pylibms-5.0.4.dist-info}/top_level.txt +0 -0
lms/common/field/io.py
CHANGED
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
from typing import Callable
|
|
2
|
-
|
|
3
|
-
from lms.common.field.lms_datatype import (
|
|
4
|
-
LMS_DataType,
|
|
5
|
-
is_bool_datatype,
|
|
6
|
-
is_enum_datatype,
|
|
7
|
-
is_number_datatype,
|
|
8
|
-
)
|
|
9
|
-
from lms.common.field.lms_field import LMS_Field
|
|
10
|
-
from lms.fileio.io import FileReader, FileWriter
|
|
11
|
-
from lms.titleconfig.definitions.field import FieldDefinition
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def read_field(
|
|
15
|
-
reader: FileReader,
|
|
16
|
-
definition: FieldDefinition,
|
|
17
|
-
read_variable_width_value: Callable | None = None,
|
|
18
|
-
) -> LMS_Field:
|
|
19
|
-
# String is excluded as their reading varies between MSBT/MSBF
|
|
20
|
-
match definition.datatype:
|
|
21
|
-
case LMS_DataType.UINT8:
|
|
22
|
-
value = reader.read_uint8()
|
|
23
|
-
case LMS_DataType.UINT16:
|
|
24
|
-
value = reader.read_uint16()
|
|
25
|
-
case LMS_DataType.UINT32:
|
|
26
|
-
value = reader.read_uint32()
|
|
27
|
-
case LMS_DataType.INT8:
|
|
28
|
-
value = reader.read_int8()
|
|
29
|
-
case LMS_DataType.INT16:
|
|
30
|
-
value = reader.read_int16()
|
|
31
|
-
case LMS_DataType.INT32:
|
|
32
|
-
value = reader.read_int32()
|
|
33
|
-
case LMS_DataType.FLOAT32:
|
|
34
|
-
value = reader.read_float32()
|
|
35
|
-
case LMS_DataType.ENUM:
|
|
36
|
-
if read_variable_width_value is not None:
|
|
37
|
-
index = read_variable_width_value()
|
|
38
|
-
else:
|
|
39
|
-
index = reader.read_uint8()
|
|
40
|
-
value = definition.enum_members[index]
|
|
41
|
-
case LMS_DataType.BOOL:
|
|
42
|
-
if read_variable_width_value is not None:
|
|
43
|
-
value = bool(read_variable_width_value())
|
|
44
|
-
else:
|
|
45
|
-
value = bool(reader.read_uint8())
|
|
46
|
-
|
|
47
|
-
return LMS_Field(value, definition)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def write_field(
|
|
51
|
-
writer: FileWriter,
|
|
52
|
-
field: LMS_Field,
|
|
53
|
-
write_variable_width_value: Callable | None = None,
|
|
54
|
-
) -> None:
|
|
55
|
-
if is_number_datatype(field.value, field.datatype):
|
|
56
|
-
write_functions: dict[LMS_DataType, Callable] = {
|
|
57
|
-
LMS_DataType.UINT8: writer.write_uint8,
|
|
58
|
-
LMS_DataType.INT8: writer.write_int8,
|
|
59
|
-
LMS_DataType.UINT16: writer.write_uint16,
|
|
60
|
-
LMS_DataType.INT16: writer.write_int16,
|
|
61
|
-
LMS_DataType.UINT32: writer.write_uint32,
|
|
62
|
-
LMS_DataType.INT32: writer.write_int32,
|
|
63
|
-
LMS_DataType.FLOAT32: writer.write_float32,
|
|
64
|
-
}
|
|
65
|
-
write_functions[field.datatype](field.value)
|
|
66
|
-
return
|
|
67
|
-
|
|
68
|
-
if is_enum_datatype(field.value, field.datatype):
|
|
69
|
-
value = list(field.enum_members.values()).index(field.value)
|
|
70
|
-
if write_variable_width_value is not None:
|
|
71
|
-
write_variable_width_value(value)
|
|
72
|
-
else:
|
|
73
|
-
writer.write_uint8(value)
|
|
74
|
-
elif is_bool_datatype(field.value, field.datatype):
|
|
75
|
-
if write_variable_width_value is not None:
|
|
76
|
-
write_variable_width_value(bool(field.value))
|
|
77
|
-
else:
|
|
78
|
-
writer.write_uint8(bool(field.value))
|
|
79
|
-
else:
|
|
80
|
-
raise ValueError(f"Unsupported datatype: {field.datatype}")
|
|
1
|
+
from typing import Callable
|
|
2
|
+
|
|
3
|
+
from lms.common.field.lms_datatype import (
|
|
4
|
+
LMS_DataType,
|
|
5
|
+
is_bool_datatype,
|
|
6
|
+
is_enum_datatype,
|
|
7
|
+
is_number_datatype,
|
|
8
|
+
)
|
|
9
|
+
from lms.common.field.lms_field import LMS_Field
|
|
10
|
+
from lms.fileio.io import FileReader, FileWriter
|
|
11
|
+
from lms.titleconfig.definitions.field import FieldDefinition
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def read_field(
|
|
15
|
+
reader: FileReader,
|
|
16
|
+
definition: FieldDefinition,
|
|
17
|
+
read_variable_width_value: Callable | None = None,
|
|
18
|
+
) -> LMS_Field:
|
|
19
|
+
# String is excluded as their reading varies between MSBT/MSBF
|
|
20
|
+
match definition.datatype:
|
|
21
|
+
case LMS_DataType.UINT8:
|
|
22
|
+
value = reader.read_uint8()
|
|
23
|
+
case LMS_DataType.UINT16:
|
|
24
|
+
value = reader.read_uint16()
|
|
25
|
+
case LMS_DataType.UINT32:
|
|
26
|
+
value = reader.read_uint32()
|
|
27
|
+
case LMS_DataType.INT8:
|
|
28
|
+
value = reader.read_int8()
|
|
29
|
+
case LMS_DataType.INT16:
|
|
30
|
+
value = reader.read_int16()
|
|
31
|
+
case LMS_DataType.INT32:
|
|
32
|
+
value = reader.read_int32()
|
|
33
|
+
case LMS_DataType.FLOAT32:
|
|
34
|
+
value = reader.read_float32()
|
|
35
|
+
case LMS_DataType.ENUM:
|
|
36
|
+
if read_variable_width_value is not None:
|
|
37
|
+
index = read_variable_width_value()
|
|
38
|
+
else:
|
|
39
|
+
index = reader.read_uint8()
|
|
40
|
+
value = definition.enum_members[index]
|
|
41
|
+
case LMS_DataType.BOOL:
|
|
42
|
+
if read_variable_width_value is not None:
|
|
43
|
+
value = bool(read_variable_width_value())
|
|
44
|
+
else:
|
|
45
|
+
value = bool(reader.read_uint8())
|
|
46
|
+
|
|
47
|
+
return LMS_Field(value, definition)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def write_field(
|
|
51
|
+
writer: FileWriter,
|
|
52
|
+
field: LMS_Field,
|
|
53
|
+
write_variable_width_value: Callable | None = None,
|
|
54
|
+
) -> None:
|
|
55
|
+
if is_number_datatype(field.value, field.datatype):
|
|
56
|
+
write_functions: dict[LMS_DataType, Callable] = {
|
|
57
|
+
LMS_DataType.UINT8: writer.write_uint8,
|
|
58
|
+
LMS_DataType.INT8: writer.write_int8,
|
|
59
|
+
LMS_DataType.UINT16: writer.write_uint16,
|
|
60
|
+
LMS_DataType.INT16: writer.write_int16,
|
|
61
|
+
LMS_DataType.UINT32: writer.write_uint32,
|
|
62
|
+
LMS_DataType.INT32: writer.write_int32,
|
|
63
|
+
LMS_DataType.FLOAT32: writer.write_float32,
|
|
64
|
+
}
|
|
65
|
+
write_functions[field.datatype](field.value)
|
|
66
|
+
return
|
|
67
|
+
|
|
68
|
+
if is_enum_datatype(field.value, field.datatype):
|
|
69
|
+
value = list(field.enum_members.values()).index(field.value)
|
|
70
|
+
if write_variable_width_value is not None:
|
|
71
|
+
write_variable_width_value(value)
|
|
72
|
+
else:
|
|
73
|
+
writer.write_uint8(value)
|
|
74
|
+
elif is_bool_datatype(field.value, field.datatype):
|
|
75
|
+
if write_variable_width_value is not None:
|
|
76
|
+
write_variable_width_value(bool(field.value))
|
|
77
|
+
else:
|
|
78
|
+
writer.write_uint8(bool(field.value))
|
|
79
|
+
else:
|
|
80
|
+
raise ValueError(f"Unsupported datatype: {field.datatype}")
|
lms/common/field/lms_datatype.py
CHANGED
|
@@ -1,152 +1,152 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from enum import IntEnum, auto
|
|
4
|
-
from typing import Type, TypeGuard
|
|
5
|
-
|
|
6
|
-
FLOAT32_MIN = -3.4028235e38
|
|
7
|
-
FLOAT32_MAX = 3.4028235e38
|
|
8
|
-
|
|
9
|
-
ALIAS_MAP = {
|
|
10
|
-
"u8": "UINT8",
|
|
11
|
-
"u16": "UINT16",
|
|
12
|
-
"u32": "UINT32",
|
|
13
|
-
"i8": "INT8",
|
|
14
|
-
"i16": "INT16",
|
|
15
|
-
"i32": "INT32",
|
|
16
|
-
"f32": "FLOAT32",
|
|
17
|
-
"str": "STRING",
|
|
18
|
-
# LIST fallback for ENUM datatype
|
|
19
|
-
"list": "ENUM",
|
|
20
|
-
"bool": "BOOL",
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
def is_number_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[int | float]:
|
|
25
|
-
if isinstance(value, float) and datatype is LMS_DataType.FLOAT32:
|
|
26
|
-
return True
|
|
27
|
-
|
|
28
|
-
return datatype in (
|
|
29
|
-
LMS_DataType.UINT8,
|
|
30
|
-
LMS_DataType.UINT16,
|
|
31
|
-
LMS_DataType.UINT32,
|
|
32
|
-
LMS_DataType.INT8,
|
|
33
|
-
LMS_DataType.INT16,
|
|
34
|
-
LMS_DataType.INT32,
|
|
35
|
-
) and isinstance(value, int)
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def is_enum_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[str]:
|
|
39
|
-
return datatype is LMS_DataType.ENUM and isinstance(value, str)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
def is_bool_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[bool]:
|
|
43
|
-
return datatype is LMS_DataType.BOOL and isinstance(value, bool)
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
def is_bytes_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[bytes]:
|
|
47
|
-
return datatype is LMS_DataType.BYTES and isinstance(value, bytes)
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def is_string_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[str]:
|
|
51
|
-
return datatype is LMS_DataType.STRING and isinstance(value, str)
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
class LMS_DataType(IntEnum):
|
|
55
|
-
"""Enum that represents a datatype for a value entry in a MSBT/MSBP file."""
|
|
56
|
-
|
|
57
|
-
UINT8 = 0
|
|
58
|
-
UINT16 = 1
|
|
59
|
-
UINT32 = 2
|
|
60
|
-
|
|
61
|
-
INT8 = 3
|
|
62
|
-
INT16 = 4
|
|
63
|
-
INT32 = 5
|
|
64
|
-
|
|
65
|
-
FLOAT32 = 6
|
|
66
|
-
|
|
67
|
-
STRING = 8
|
|
68
|
-
ENUM = 9
|
|
69
|
-
|
|
70
|
-
# Interface type for UINT8
|
|
71
|
-
BOOL = auto()
|
|
72
|
-
|
|
73
|
-
@property
|
|
74
|
-
def signed(self) -> bool:
|
|
75
|
-
"""Property for if the type is signed or not."""
|
|
76
|
-
if self not in [
|
|
77
|
-
self.STRING,
|
|
78
|
-
self.ENUM,
|
|
79
|
-
self.BOOL,
|
|
80
|
-
]:
|
|
81
|
-
return self in [self.INT8, self.INT16, self.INT32]
|
|
82
|
-
|
|
83
|
-
raise TypeError(f"Signed is not a valid property for '{self.name.lower()}'!")
|
|
84
|
-
|
|
85
|
-
@property
|
|
86
|
-
def builtin_type(self) -> Type[int | float | str | bool | bytes]:
|
|
87
|
-
"""The enum as the builtin python type."""
|
|
88
|
-
return {
|
|
89
|
-
self.UINT8: int,
|
|
90
|
-
self.UINT16: int,
|
|
91
|
-
self.UINT32: int,
|
|
92
|
-
self.INT8: int,
|
|
93
|
-
self.INT16: int,
|
|
94
|
-
self.INT32: int,
|
|
95
|
-
self.FLOAT32: float,
|
|
96
|
-
self.STRING: str,
|
|
97
|
-
self.ENUM: str,
|
|
98
|
-
self.BOOL: bool,
|
|
99
|
-
}[self]
|
|
100
|
-
|
|
101
|
-
@property
|
|
102
|
-
def stream_size(self) -> int:
|
|
103
|
-
"""Size of the datatype, only for fixed integers."""
|
|
104
|
-
sizes = {
|
|
105
|
-
self.UINT8: 1,
|
|
106
|
-
self.UINT16: 2,
|
|
107
|
-
self.UINT32: 4,
|
|
108
|
-
self.INT8: 1,
|
|
109
|
-
self.INT16: 2,
|
|
110
|
-
self.INT32: 4,
|
|
111
|
-
self.FLOAT32: 4,
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
try:
|
|
115
|
-
return sizes[self]
|
|
116
|
-
except KeyError:
|
|
117
|
-
raise TypeError(f"Stream size is not defined for '{self.name.lower()}'.")
|
|
118
|
-
|
|
119
|
-
@classmethod
|
|
120
|
-
def from_string(cls, string: str):
|
|
121
|
-
"""Creates an enum value from its string representation"""
|
|
122
|
-
member = string.upper()
|
|
123
|
-
if member in cls.__members__:
|
|
124
|
-
return cls[member]
|
|
125
|
-
|
|
126
|
-
alias_member = ALIAS_MAP.get(string.lower())
|
|
127
|
-
if alias_member is not None:
|
|
128
|
-
return cls[alias_member]
|
|
129
|
-
else:
|
|
130
|
-
raise ValueError(f"Unknown value of '{string}' was provided!")
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
def verify_number_from_datatype(
|
|
134
|
-
value: int | float,
|
|
135
|
-
datatype: LMS_DataType,
|
|
136
|
-
):
|
|
137
|
-
if datatype is LMS_DataType.FLOAT32:
|
|
138
|
-
max_value = FLOAT32_MAX
|
|
139
|
-
min_value = FLOAT32_MIN
|
|
140
|
-
else:
|
|
141
|
-
bits = datatype.stream_size * 8
|
|
142
|
-
if datatype.signed:
|
|
143
|
-
min_value = -(2 ** (bits - 1))
|
|
144
|
-
max_value = (2 ** (bits - 1)) - 1
|
|
145
|
-
else:
|
|
146
|
-
min_value, max_value = 0, (2 ** bits) - 1
|
|
147
|
-
|
|
148
|
-
if not min_value <= value <= max_value:
|
|
149
|
-
raise ValueError(
|
|
150
|
-
f"""The value '{value}' of type '{datatype.name}' provided
|
|
151
|
-
is out of range of ({min_value}, {max_value})"""
|
|
152
|
-
)
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from enum import IntEnum, auto
|
|
4
|
+
from typing import Type, TypeGuard
|
|
5
|
+
|
|
6
|
+
FLOAT32_MIN = -3.4028235e38
|
|
7
|
+
FLOAT32_MAX = 3.4028235e38
|
|
8
|
+
|
|
9
|
+
ALIAS_MAP = {
|
|
10
|
+
"u8": "UINT8",
|
|
11
|
+
"u16": "UINT16",
|
|
12
|
+
"u32": "UINT32",
|
|
13
|
+
"i8": "INT8",
|
|
14
|
+
"i16": "INT16",
|
|
15
|
+
"i32": "INT32",
|
|
16
|
+
"f32": "FLOAT32",
|
|
17
|
+
"str": "STRING",
|
|
18
|
+
# LIST fallback for ENUM datatype
|
|
19
|
+
"list": "ENUM",
|
|
20
|
+
"bool": "BOOL",
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def is_number_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[int | float]:
|
|
25
|
+
if isinstance(value, float) and datatype is LMS_DataType.FLOAT32:
|
|
26
|
+
return True
|
|
27
|
+
|
|
28
|
+
return datatype in (
|
|
29
|
+
LMS_DataType.UINT8,
|
|
30
|
+
LMS_DataType.UINT16,
|
|
31
|
+
LMS_DataType.UINT32,
|
|
32
|
+
LMS_DataType.INT8,
|
|
33
|
+
LMS_DataType.INT16,
|
|
34
|
+
LMS_DataType.INT32,
|
|
35
|
+
) and isinstance(value, int)
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def is_enum_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[str]:
|
|
39
|
+
return datatype is LMS_DataType.ENUM and isinstance(value, str)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def is_bool_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[bool]:
|
|
43
|
+
return datatype is LMS_DataType.BOOL and isinstance(value, bool)
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
def is_bytes_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[bytes]:
|
|
47
|
+
return datatype is LMS_DataType.BYTES and isinstance(value, bytes)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def is_string_datatype(value: object, datatype: LMS_DataType) -> TypeGuard[str]:
|
|
51
|
+
return datatype is LMS_DataType.STRING and isinstance(value, str)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class LMS_DataType(IntEnum):
|
|
55
|
+
"""Enum that represents a datatype for a value entry in a MSBT/MSBP file."""
|
|
56
|
+
|
|
57
|
+
UINT8 = 0
|
|
58
|
+
UINT16 = 1
|
|
59
|
+
UINT32 = 2
|
|
60
|
+
|
|
61
|
+
INT8 = 3
|
|
62
|
+
INT16 = 4
|
|
63
|
+
INT32 = 5
|
|
64
|
+
|
|
65
|
+
FLOAT32 = 6
|
|
66
|
+
|
|
67
|
+
STRING = 8
|
|
68
|
+
ENUM = 9
|
|
69
|
+
|
|
70
|
+
# Interface type for UINT8
|
|
71
|
+
BOOL = auto()
|
|
72
|
+
|
|
73
|
+
@property
|
|
74
|
+
def signed(self) -> bool:
|
|
75
|
+
"""Property for if the type is signed or not."""
|
|
76
|
+
if self not in [
|
|
77
|
+
self.STRING,
|
|
78
|
+
self.ENUM,
|
|
79
|
+
self.BOOL,
|
|
80
|
+
]:
|
|
81
|
+
return self in [self.INT8, self.INT16, self.INT32]
|
|
82
|
+
|
|
83
|
+
raise TypeError(f"Signed is not a valid property for '{self.name.lower()}'!")
|
|
84
|
+
|
|
85
|
+
@property
|
|
86
|
+
def builtin_type(self) -> Type[int | float | str | bool | bytes]:
|
|
87
|
+
"""The enum as the builtin python type."""
|
|
88
|
+
return {
|
|
89
|
+
self.UINT8: int,
|
|
90
|
+
self.UINT16: int,
|
|
91
|
+
self.UINT32: int,
|
|
92
|
+
self.INT8: int,
|
|
93
|
+
self.INT16: int,
|
|
94
|
+
self.INT32: int,
|
|
95
|
+
self.FLOAT32: float,
|
|
96
|
+
self.STRING: str,
|
|
97
|
+
self.ENUM: str,
|
|
98
|
+
self.BOOL: bool,
|
|
99
|
+
}[self]
|
|
100
|
+
|
|
101
|
+
@property
|
|
102
|
+
def stream_size(self) -> int:
|
|
103
|
+
"""Size of the datatype, only for fixed integers."""
|
|
104
|
+
sizes = {
|
|
105
|
+
self.UINT8: 1,
|
|
106
|
+
self.UINT16: 2,
|
|
107
|
+
self.UINT32: 4,
|
|
108
|
+
self.INT8: 1,
|
|
109
|
+
self.INT16: 2,
|
|
110
|
+
self.INT32: 4,
|
|
111
|
+
self.FLOAT32: 4,
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
try:
|
|
115
|
+
return sizes[self]
|
|
116
|
+
except KeyError:
|
|
117
|
+
raise TypeError(f"Stream size is not defined for '{self.name.lower()}'.")
|
|
118
|
+
|
|
119
|
+
@classmethod
|
|
120
|
+
def from_string(cls, string: str):
|
|
121
|
+
"""Creates an enum value from its string representation"""
|
|
122
|
+
member = string.upper()
|
|
123
|
+
if member in cls.__members__:
|
|
124
|
+
return cls[member]
|
|
125
|
+
|
|
126
|
+
alias_member = ALIAS_MAP.get(string.lower())
|
|
127
|
+
if alias_member is not None:
|
|
128
|
+
return cls[alias_member]
|
|
129
|
+
else:
|
|
130
|
+
raise ValueError(f"Unknown value of '{string}' was provided!")
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def verify_number_from_datatype(
|
|
134
|
+
value: int | float,
|
|
135
|
+
datatype: LMS_DataType,
|
|
136
|
+
):
|
|
137
|
+
if datatype is LMS_DataType.FLOAT32:
|
|
138
|
+
max_value = FLOAT32_MAX
|
|
139
|
+
min_value = FLOAT32_MIN
|
|
140
|
+
else:
|
|
141
|
+
bits = datatype.stream_size * 8
|
|
142
|
+
if datatype.signed:
|
|
143
|
+
min_value = -(2 ** (bits - 1))
|
|
144
|
+
max_value = (2 ** (bits - 1)) - 1
|
|
145
|
+
else:
|
|
146
|
+
min_value, max_value = 0, (2 ** bits) - 1
|
|
147
|
+
|
|
148
|
+
if not min_value <= value <= max_value:
|
|
149
|
+
raise ValueError(
|
|
150
|
+
f"""The value '{value}' of type '{datatype.name}' provided
|
|
151
|
+
is out of range of ({min_value}, {max_value})"""
|
|
152
|
+
)
|