sltcore 0.2.1__tar.gz → 0.2.3__tar.gz

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.
@@ -0,0 +1,43 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: write
8
+
9
+ jobs:
10
+ build-and-publish:
11
+ runs-on: ubuntu-latest
12
+
13
+ steps:
14
+ - uses: actions/checkout@v4
15
+
16
+ - name: Extract version from pyproject.toml
17
+ id: version
18
+ run: |
19
+ VERSION=$(grep -m1 '^version = "' pyproject.toml | sed -E 's/^version = "([^"]+)"$/\1/')
20
+ echo "version=$VERSION" >> "$GITHUB_OUTPUT"
21
+ echo "tag=v$VERSION" >> "$GITHUB_OUTPUT"
22
+
23
+ - name: Install uv
24
+ uses: astral-sh/setup-uv@v3
25
+
26
+ - name: Build distribution
27
+ run: uv build
28
+
29
+ - name: Publish to PyPI
30
+ uses: pypa/gh-action-pypi-publish@release/v1
31
+ with:
32
+ password: ${{ secrets.PYPI_API_TOKEN }}
33
+ packages-dir: dist
34
+
35
+ - name: Create GitHub release and upload artifacts
36
+ uses: softprops/action-gh-release@v2
37
+ with:
38
+ tag_name: ${{ steps.version.outputs.tag }}
39
+ name: ${{ steps.version.outputs.tag }}
40
+ generate_release_notes: true
41
+ files: |
42
+ dist/*.tar.gz
43
+ dist/*.whl
@@ -2,8 +2,6 @@ name: Publish to TestPyPI
2
2
 
3
3
  on:
4
4
  workflow_dispatch:
5
- release:
6
- types: [published]
7
5
 
8
6
  jobs:
9
7
  build-and-publish:
@@ -23,4 +21,4 @@ jobs:
23
21
  with:
24
22
  password: ${{ secrets.TEST_PYPI_API_TOKEN }}
25
23
  repository-url: https://test.pypi.org/legacy/
26
- packages_dir: dist
24
+ packages-dir: dist
sltcore-0.2.3/PKG-INFO ADDED
@@ -0,0 +1,151 @@
1
+ Metadata-Version: 2.4
2
+ Name: sltcore
3
+ Version: 0.2.3
4
+ Summary: A toolkit for handling structured data layouts and bit-level operations.
5
+ Project-URL: Homepage, https://github.com/fangface-hub/StructLayoutToolkitCore
6
+ Project-URL: Documentation, https://readthedocs.org
7
+ Project-URL: Repository, https://github.com/fangface-hub/StructLayoutToolkitCore
8
+ Project-URL: Issues, https://github.com/fangface-hub/StructLayoutToolkitCore/issues
9
+ Author: fangface
10
+ License-Expression: MIT
11
+ License-File: LICENSE
12
+ Keywords: bit,byte,data,deserialization,layout,serialization,struct
13
+ Requires-Python: >=3.12
14
+ Description-Content-Type: text/markdown
15
+
16
+ # StructLayoutToolkitCore
17
+
18
+ stlcore is a minimal, high‑cohesion core library for bit‑accurate binary slicing. It provides the fundamental primitives (bits_get, bits_set, InfoSize) required to build struct layout analyzers, binary editors, protocol inspectors, and low‑level testing tools. Designed for clarity, correctness, and composability.
19
+
20
+ ## What You Can Do After Installing sltcore
21
+
22
+ sltcore provides a minimal and consistent bit-level abstraction layer for building higher‑level tools such as binary editors, protocol analyzers, and structured layout systems.
23
+
24
+ After installing the package, you can:
25
+
26
+ - Extract arbitrary bit ranges from a bytearray using bits_get
27
+ - Write arbitrary bit ranges into a bytearray using bits_set
28
+ - Represent sizes and offsets uniformly with InfoSize
29
+ - Build structured binary layouts on top of a stable bit‑operation core
30
+
31
+ ## Quick Examples: bits_get / bits_set
32
+
33
+ ```python
34
+
35
+ from sltcore import InfoSize, Info , bits_get, bits_set
36
+
37
+ buf = bytearray(b"\x12\x34\x56\x78")
38
+
39
+ # Extract 4 bits at offset (1 byte, 0 bits)
40
+ value = bits_get(buf, InfoSize(1, 0), InfoSize(0, 4))
41
+ print(value.to_hex) # 0x3
42
+
43
+ # Write 5 bits at offset (2 bytes, 3 bits)
44
+ bits_set(buf, InfoSize(2, 3), InfoSize(0, 5), 0b10101)
45
+ print(buf.hex()) # 12345578
46
+
47
+ ```
48
+
49
+ ## sltcore.InfoSize
50
+
51
+ InfoSize is a type that represents offsets and sizes in a unified way.
52
+ It supports addition and subtraction, and stores both byte and bit components.
53
+
54
+ It is used for both offset and size, allowing consistent structural layout definitions.
55
+
56
+ - __Field List__
57
+
58
+ | Field | Type | Description |
59
+ | --- | --- | --- |
60
+ | byte | int | the byte size |
61
+ | bit | int | the bit size (0–7)<br> always normalized so that bit < 8 |
62
+
63
+ - __Property List__
64
+
65
+ | Property | Type | Description |
66
+ | --- | --- | --- |
67
+ | bits | int | Total bit length.<br> This property converts the stored byte and bit components into a single bit count using the formula byte * 8 + bit |
68
+ | bytes | int | Total byte length.<br> This property converts the combined bit length (byte * 8 + bit) into a byte count using integer division (bits // 8) |
69
+ | hex_digits | int | Number of hexadecimal digits needed to represent the field.<br>Since one hex digit corresponds to 4 bits, the value is calculated as ceil(bits / 4) |
70
+ | mask | int | Bitmask for the field size.<br>It produces a mask that covers exactly bits bits, using the formula (1 << bits) - 1.<br>This mask is typically used for extracting or normalizing values. |
71
+
72
+ ## sltcore.Info
73
+
74
+ Info stores an InfoSize and a raw integer value.
75
+
76
+ This allows higher‑level code to treat extracted fields as structured units rather than plain integers.
77
+
78
+ - __Field List__
79
+
80
+ | Field | Type | Description |
81
+ | --- | --- | --- |
82
+ | raw_value | int | The internal integer representation of the field.<br>It is obtained by converting the corresponding bytes into an integer and applying the size mask so that the value fits within the bit width specified by InfoSize. |
83
+ | info_size | InfoSize | Size descriptor for this value.<br>It provides the byte and bit length of the field and determines how the raw_value is masked, extracted, and written back into the byte sequence. |
84
+
85
+ - __Classmethod List__
86
+
87
+ | Classmethod | Description |
88
+ | --- | --- |
89
+ | from_int | Creates an Info instance from an integer value, ensuring that the value fits within the specified size by applying a bitmask. |
90
+ | from_bytes | Creates an Info instance from a bytes object, ensuring that the value fits within the specified size by applying a bitmask. |
91
+ | from_bytearray | Creates an Info instance from a bytearray, ensuring that the value fits within the specified size by applying a bitmask. |
92
+ | from_float | Creates an Info instance from a float value, converting it to its raw bit representation based on the specified size. |
93
+
94
+ Example: Creating an Info from a float value
95
+
96
+ ```python
97
+ size = InfoSize(byte=0, bit=32) # 32-bit float
98
+ info = Info.from_float(3.14, size)
99
+
100
+ print(info.raw_value) # IEEE754 raw bits (e.g., 0x4048F5C3)
101
+ print(info.info_size.bits) # 32
102
+ ```
103
+
104
+ - __Property List__
105
+
106
+ | Property | Type | Description |
107
+ | --- | --- | --- |
108
+ | to_unsigned_int | int | Returns the extracted bits as an unsigned integer. |
109
+ | to_signed_int | int | Returns the extracted bits as a signed integer. |
110
+ | to_hex | str | Returns the extracted bits as a hexadecimal string. |
111
+ | to_bytes | bytes | Returns the extracted bits as a bytes object. |
112
+ | to_bool | bool | Returns the extracted bits as a boolean value. |
113
+ | to_float | float | Returns the extracted bits as a float. |
114
+ | byte_swap | Info | Returns a new Info instance with the byte order reversed. |
115
+
116
+ ## sltcore.bits_get
117
+
118
+ bits_get extracts a field from a bytearray using an offset and size, and returns an Info object.
119
+
120
+ Input:
121
+
122
+ - bytearray buffer
123
+ - InfoSize offset
124
+ - InfoSize size
125
+
126
+ Output:
127
+
128
+ - Info containing the extracted value and its size
129
+
130
+ ## sltcore.bits_set
131
+
132
+ bits_set writes a value into a bytearray at the specified offset.
133
+
134
+ Input:
135
+
136
+ - bytearray buffer
137
+ - InfoSize offset
138
+ - Info value (which includes its size)
139
+
140
+ The function masks and replaces the target bit range inside the buffer.
141
+
142
+ ## Documentation
143
+
144
+ For detailed usage, examples, and parameter descriptions, refer to the docstrings via:
145
+
146
+ python
147
+
148
+ - help(sltcore.InfoSize)
149
+ - help(sltcore.Info)
150
+ - help(sltcore.bits_get)
151
+ - help(sltcore.bits_set)
@@ -0,0 +1,136 @@
1
+ # StructLayoutToolkitCore
2
+
3
+ stlcore is a minimal, high‑cohesion core library for bit‑accurate binary slicing. It provides the fundamental primitives (bits_get, bits_set, InfoSize) required to build struct layout analyzers, binary editors, protocol inspectors, and low‑level testing tools. Designed for clarity, correctness, and composability.
4
+
5
+ ## What You Can Do After Installing sltcore
6
+
7
+ sltcore provides a minimal and consistent bit-level abstraction layer for building higher‑level tools such as binary editors, protocol analyzers, and structured layout systems.
8
+
9
+ After installing the package, you can:
10
+
11
+ - Extract arbitrary bit ranges from a bytearray using bits_get
12
+ - Write arbitrary bit ranges into a bytearray using bits_set
13
+ - Represent sizes and offsets uniformly with InfoSize
14
+ - Build structured binary layouts on top of a stable bit‑operation core
15
+
16
+ ## Quick Examples: bits_get / bits_set
17
+
18
+ ```python
19
+
20
+ from sltcore import InfoSize, Info , bits_get, bits_set
21
+
22
+ buf = bytearray(b"\x12\x34\x56\x78")
23
+
24
+ # Extract 4 bits at offset (1 byte, 0 bits)
25
+ value = bits_get(buf, InfoSize(1, 0), InfoSize(0, 4))
26
+ print(value.to_hex) # 0x3
27
+
28
+ # Write 5 bits at offset (2 bytes, 3 bits)
29
+ bits_set(buf, InfoSize(2, 3), InfoSize(0, 5), 0b10101)
30
+ print(buf.hex()) # 12345578
31
+
32
+ ```
33
+
34
+ ## sltcore.InfoSize
35
+
36
+ InfoSize is a type that represents offsets and sizes in a unified way.
37
+ It supports addition and subtraction, and stores both byte and bit components.
38
+
39
+ It is used for both offset and size, allowing consistent structural layout definitions.
40
+
41
+ - __Field List__
42
+
43
+ | Field | Type | Description |
44
+ | --- | --- | --- |
45
+ | byte | int | the byte size |
46
+ | bit | int | the bit size (0–7)<br> always normalized so that bit < 8 |
47
+
48
+ - __Property List__
49
+
50
+ | Property | Type | Description |
51
+ | --- | --- | --- |
52
+ | bits | int | Total bit length.<br> This property converts the stored byte and bit components into a single bit count using the formula byte * 8 + bit |
53
+ | bytes | int | Total byte length.<br> This property converts the combined bit length (byte * 8 + bit) into a byte count using integer division (bits // 8) |
54
+ | hex_digits | int | Number of hexadecimal digits needed to represent the field.<br>Since one hex digit corresponds to 4 bits, the value is calculated as ceil(bits / 4) |
55
+ | mask | int | Bitmask for the field size.<br>It produces a mask that covers exactly bits bits, using the formula (1 << bits) - 1.<br>This mask is typically used for extracting or normalizing values. |
56
+
57
+ ## sltcore.Info
58
+
59
+ Info stores an InfoSize and a raw integer value.
60
+
61
+ This allows higher‑level code to treat extracted fields as structured units rather than plain integers.
62
+
63
+ - __Field List__
64
+
65
+ | Field | Type | Description |
66
+ | --- | --- | --- |
67
+ | raw_value | int | The internal integer representation of the field.<br>It is obtained by converting the corresponding bytes into an integer and applying the size mask so that the value fits within the bit width specified by InfoSize. |
68
+ | info_size | InfoSize | Size descriptor for this value.<br>It provides the byte and bit length of the field and determines how the raw_value is masked, extracted, and written back into the byte sequence. |
69
+
70
+ - __Classmethod List__
71
+
72
+ | Classmethod | Description |
73
+ | --- | --- |
74
+ | from_int | Creates an Info instance from an integer value, ensuring that the value fits within the specified size by applying a bitmask. |
75
+ | from_bytes | Creates an Info instance from a bytes object, ensuring that the value fits within the specified size by applying a bitmask. |
76
+ | from_bytearray | Creates an Info instance from a bytearray, ensuring that the value fits within the specified size by applying a bitmask. |
77
+ | from_float | Creates an Info instance from a float value, converting it to its raw bit representation based on the specified size. |
78
+
79
+ Example: Creating an Info from a float value
80
+
81
+ ```python
82
+ size = InfoSize(byte=0, bit=32) # 32-bit float
83
+ info = Info.from_float(3.14, size)
84
+
85
+ print(info.raw_value) # IEEE754 raw bits (e.g., 0x4048F5C3)
86
+ print(info.info_size.bits) # 32
87
+ ```
88
+
89
+ - __Property List__
90
+
91
+ | Property | Type | Description |
92
+ | --- | --- | --- |
93
+ | to_unsigned_int | int | Returns the extracted bits as an unsigned integer. |
94
+ | to_signed_int | int | Returns the extracted bits as a signed integer. |
95
+ | to_hex | str | Returns the extracted bits as a hexadecimal string. |
96
+ | to_bytes | bytes | Returns the extracted bits as a bytes object. |
97
+ | to_bool | bool | Returns the extracted bits as a boolean value. |
98
+ | to_float | float | Returns the extracted bits as a float. |
99
+ | byte_swap | Info | Returns a new Info instance with the byte order reversed. |
100
+
101
+ ## sltcore.bits_get
102
+
103
+ bits_get extracts a field from a bytearray using an offset and size, and returns an Info object.
104
+
105
+ Input:
106
+
107
+ - bytearray buffer
108
+ - InfoSize offset
109
+ - InfoSize size
110
+
111
+ Output:
112
+
113
+ - Info containing the extracted value and its size
114
+
115
+ ## sltcore.bits_set
116
+
117
+ bits_set writes a value into a bytearray at the specified offset.
118
+
119
+ Input:
120
+
121
+ - bytearray buffer
122
+ - InfoSize offset
123
+ - Info value (which includes its size)
124
+
125
+ The function masks and replaces the target bit range inside the buffer.
126
+
127
+ ## Documentation
128
+
129
+ For detailed usage, examples, and parameter descriptions, refer to the docstrings via:
130
+
131
+ python
132
+
133
+ - help(sltcore.InfoSize)
134
+ - help(sltcore.Info)
135
+ - help(sltcore.bits_get)
136
+ - help(sltcore.bits_set)
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sltcore"
3
- version = "0.2.1"
3
+ version = "0.2.3"
4
4
  license = "MIT"
5
5
  license-files = ["LICENSE"]
6
6
  description = "A toolkit for handling structured data layouts and bit-level operations."
@@ -0,0 +1,4 @@
1
+ from .bits import bits_get, bits_set
2
+ from .types import Info, InfoSize
3
+
4
+ __all__ = ["bits_get", "bits_set", "InfoSize", "Info"]
@@ -1,37 +1,52 @@
1
1
  """Type definitions for structured data layouts and bit-level operations."""
2
2
  import math
3
- from dataclasses import dataclass
3
+ import struct
4
+ from dataclasses import dataclass, field
5
+
6
+
7
+ def _has_struct_half():
8
+ """Checks if the current Python environment supports
9
+ half-precision (16-bit) floats in the struct module."""
10
+ try:
11
+ struct.pack(">e", 1.0)
12
+ return True
13
+ except struct.error:
14
+ return False
15
+
16
+
17
+ HAS_STRUCT_HALF = _has_struct_half() # ← 一度だけ実行
4
18
 
5
19
 
6
20
  @dataclass(frozen=True)
7
21
  class InfoSize:
8
22
  """Represents a size in bytes and bits."""
9
- byte: int = 0
10
- bit: int = 0
23
+ byte: int = field(default=0, metadata={"desc": "byte size"})
24
+ bit: int = field(default=0, metadata={"desc": "bit size"})
11
25
 
12
26
  def __post_init__(self):
13
27
  """Ensures that the bit count is normalized to be less than 8,
14
28
  and adjusts the byte count accordingly."""
15
- extra_bytes, new_bits = divmod(self.bit, 8)
29
+ extra_bytes = self.bit >> 3
30
+ new_bits = self.bit & 7
16
31
  object.__setattr__(self, "byte", self.byte + extra_bytes)
17
32
  object.__setattr__(self, "bit", new_bits)
18
33
 
19
34
  @property
20
35
  def bits(self) -> int:
21
36
  """Returns the total size in bits."""
22
- return self.byte * 8 + self.bit
37
+ return ((self.byte << 3) | self.bit)
23
38
 
24
39
  @property
25
40
  def bytes(self) -> int:
26
41
  """Returns the total size in bytes,
27
42
  rounding up if there are leftover bits."""
28
- return (self.bits + 7) // 8 # round up
43
+ return ((self.bits + 7) >> 3) # round up
29
44
 
30
45
  @property
31
46
  def hex_digits(self) -> int:
32
47
  """Returns the number of hexadecimal digits
33
48
  needed to represent the size in bits."""
34
- return self.bits // 4
49
+ return (self.bits >> 2)
35
50
 
36
51
  @property
37
52
  def mask(self) -> int:
@@ -59,8 +74,9 @@ class InfoSize:
59
74
  class Info:
60
75
  """Represents a slice of bits extracted from a bytearray,
61
76
  along with its size information."""
62
- raw_value: int
63
- info_size: InfoSize
77
+ raw_value: int = field(default=0, metadata={"desc": "raw integer value"})
78
+ info_size: InfoSize = field(default_factory=InfoSize,
79
+ metadata={"desc": "size information"})
64
80
 
65
81
  @classmethod
66
82
  def from_int(cls, value: int, size: InfoSize):
@@ -135,65 +151,52 @@ def _float_from_bits(raw: int, bits: int) -> float:
135
151
  to a Python float, based on the specified bit size.
136
152
  Supports 16, 32, and 64 bits.
137
153
  """
138
- if bits == 16:
139
- # IEEE754 half-precision (16bit) → float32
140
- s = (raw >> 15) & 0x0001
141
- e = (raw >> 10) & 0x001F
142
- f = raw & 0x03FF
143
-
144
- if e == 0:
145
- if f == 0:
146
- return (-1)**s * 0.0
147
- return (-1)**s * (f / 2**10) * 2**(-14)
148
- elif e == 31:
149
- if f == 0:
150
- return float('inf') if s == 0 else float('-inf')
151
- return float('nan')
152
- else:
153
- return (-1)**s * (1 + f / 2**10) * 2**(e - 15)
154
- elif bits == 32:
155
- # IEEE754 single precision
156
- # High-speed version without using struct
157
- s = (raw >> 31) & 0x1
158
-
159
- e = (raw >> 23) & 0xFF
160
- f = raw & 0x7FFFFF
161
-
162
- if e == 0:
163
- return (-1)**s * (f / 2**23) * 2**(-126)
164
- elif e == 255:
165
- if f == 0:
166
- return float('-inf') if s else float('inf')
167
- return float('nan')
168
- else:
169
- return (-1)**s * (1 + f / 2**23) * 2**(e - 127)
170
-
171
- elif bits == 64:
172
- # IEEE754 double precision
173
- s = (raw >> 63) & 0x1
174
- e = (raw >> 52) & 0x7FF
175
- f = raw & 0xFFFFFFFFFFFFF
176
-
177
- if e == 0:
178
- return (-1)**s * (f / 2**52) * 2**(-1022)
179
- elif e == 2047:
180
- if f == 0:
181
- return float('-inf') if s else float('inf')
182
- return float('nan')
183
- else:
184
- return (-1)**s * (1 + f / 2**52) * 2**(e - 1023)
185
-
186
- else:
187
- raise ValueError(''.join([
188
- f"Unsupported bit size for float conversion: {bits}. ",
154
+ if bits == 64:
155
+ return struct.unpack('>d', struct.pack('>Q', raw))[0]
156
+ if bits == 32:
157
+ # Use struct to unpack the integer as a float
158
+ return struct.unpack('>f', struct.pack('>I', raw))[0]
159
+ if bits != 16:
160
+ raise ValueError("".join([
161
+ f"Unsupported float bit size: {bits}. ",
189
162
  "Only 16, 32, and 64 are supported."
190
163
  ]))
164
+ if HAS_STRUCT_HALF:
165
+ # Use struct to unpack the integer as a half-precision float
166
+ return struct.unpack('>e', struct.pack('>H', raw))[0]
167
+ # IEEE754 half-precision (16bit) → float32
168
+ s = (raw >> 15) & 0x0001
169
+ e = (raw >> 10) & 0x001F
170
+ f = raw & 0x03FF
171
+
172
+ if e == 0:
173
+ if f == 0:
174
+ return (-1)**s * 0.0
175
+ return (-1)**s * (f / 2**10) * 2**(-14)
176
+ if e == 31:
177
+ if f == 0:
178
+ return float('inf') if s == 0 else float('-inf')
179
+ return float('nan')
180
+ return (-1)**s * (1 + f / 2**10) * 2**(e - 15)
191
181
 
192
182
 
193
183
  def _float_to_bits(value: float, bits: int) -> int:
194
184
  """Converts a Python float to its raw integer representation
195
185
  based on the specified bit size. Supports 16, 32, and 64 bits.
196
186
  """
187
+ if bits == 64:
188
+ return struct.unpack('>Q', struct.pack('>d', value))[0]
189
+ if bits == 32:
190
+ # Use struct to pack the float into bytes and then unpack as an integer
191
+ return struct.unpack('>I', struct.pack('>f', value))[0]
192
+ if bits != 16:
193
+ raise ValueError("".join([
194
+ f"Unsupported float bit size: {bits}. ",
195
+ "Only 16, 32, and 64 are supported."
196
+ ]))
197
+ if HAS_STRUCT_HALF:
198
+ # Use struct to pack the float into bytes and then unpack as an integer
199
+ return struct.unpack('>H', struct.pack('>e', value))[0]
197
200
  # Determine the sign and absolute value
198
201
  # Use math.copysign to correctly detect negative zero
199
202
  sign = 1 if math.copysign(1.0, value) < 0 else 0
@@ -205,40 +208,16 @@ def _float_to_bits(value: float, bits: int) -> int:
205
208
 
206
209
  # NaN / Inf
207
210
  if math.isnan(value):
208
- if bits == 16:
209
- return 0x7E00
210
- if bits == 32:
211
- return 0x7FC00000
212
- if bits == 64:
213
- return 0x7FF8000000000000
211
+ return 0x7E00
214
212
 
215
213
  # Handle infinity
216
214
  if math.isinf(value):
217
- if bits == 16:
218
- return (sign << 15) | 0x7C00
219
- if bits == 32:
220
- return (sign << 31) | 0x7F800000
221
- if bits == 64:
222
- return (sign << 63) | 0x7FF0000000000000
215
+ return (sign << 15) | 0x7C00
223
216
 
224
217
  # Compute exponent and mantissa
225
218
  e = int(math.floor(math.log(v, 2)))
226
219
  mant = v / (2**e) - 1.0
227
220
 
228
- if bits == 16:
229
- exp = e + 15
230
- frac = int(mant * (2**10))
231
- return (sign << 15) | (exp << 10) | frac
232
-
233
- elif bits == 32:
234
- exp = e + 127
235
- frac = int(mant * (2**23))
236
- return (sign << 31) | (exp << 23) | frac
237
-
238
- elif bits == 64:
239
- exp = e + 1023
240
- frac = int(mant * (2**52))
241
- return (sign << 63) | (exp << 52) | frac
242
-
243
- else:
244
- raise ValueError(f"Unsupported float bit size: {bits}")
221
+ exp = e + 15
222
+ frac = int(mant * (2**10))
223
+ return (sign << 15) | (exp << 10) | frac
@@ -65,7 +65,7 @@ wheels = [
65
65
 
66
66
  [[package]]
67
67
  name = "sltcore"
68
- version = "0.1.0"
68
+ version = "0.2.2"
69
69
  source = { editable = "." }
70
70
 
71
71
  [package.dev-dependencies]
@@ -1,25 +0,0 @@
1
- name: Publish to PyPI
2
-
3
- on:
4
- workflow_dispatch:
5
- release:
6
- types: [published]
7
-
8
- jobs:
9
- build-and-publish:
10
- runs-on: ubuntu-latest
11
-
12
- steps:
13
- - uses: actions/checkout@v4
14
-
15
- - name: Install uv
16
- uses: astral-sh/setup-uv@v3
17
-
18
- - name: Build wheel
19
- run: uv build
20
-
21
- - name: Publish to PyPI
22
- uses: pypa/gh-action-pypi-publish@release/v1
23
- with:
24
- password: ${{ secrets.PYPI_API_TOKEN }}
25
- packages_dir: dist
sltcore-0.2.1/PKG-INFO DELETED
@@ -1,106 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: sltcore
3
- Version: 0.2.1
4
- Summary: A toolkit for handling structured data layouts and bit-level operations.
5
- Project-URL: Homepage, https://github.com/fangface-hub/StructLayoutToolkitCore
6
- Project-URL: Documentation, https://readthedocs.org
7
- Project-URL: Repository, https://github.com/fangface-hub/StructLayoutToolkitCore
8
- Project-URL: Issues, https://github.com/fangface-hub/StructLayoutToolkitCore/issues
9
- Author: fangface
10
- License-Expression: MIT
11
- License-File: LICENSE
12
- Keywords: bit,byte,data,deserialization,layout,serialization,struct
13
- Requires-Python: >=3.12
14
- Description-Content-Type: text/markdown
15
-
16
- # StructLayoutToolkitCore
17
-
18
- stlcore is a minimal, high‑cohesion core library for bit‑accurate binary slicing. It provides the fundamental primitives (bits_get, bits_set, InfoSize) required to build struct layout analyzers, binary editors, protocol inspectors, and low‑level testing tools. Designed for clarity, correctness, and composability.
19
-
20
- ## What You Can Do After Installing sltcore
21
-
22
- sltcore provides a minimal and consistent bit-level abstraction layer for building higher‑level tools such as binary editors, protocol analyzers, and structured layout systems.
23
-
24
- After installing the package, you can:
25
-
26
- - Extract arbitrary bit ranges from a bytearray using bits_get
27
- - Write arbitrary bit ranges into a bytearray using bits_set
28
- - Represent sizes and offsets uniformly with InfoSize
29
- - Build structured binary layouts on top of a stable bit‑operation core
30
-
31
- ## Quick Examples: bits_get / bits_set
32
-
33
- ```python
34
-
35
- from sltcore.types import InfoSize, Info
36
- from sltcore.bits import bits_get, bits_set
37
-
38
- buf = bytearray(b"\x12\x34\x56\x78")
39
-
40
- # Extract 4 bits at offset (1 byte, 0 bits)
41
- value = bits_get(buf, InfoSize(1, 0), InfoSize(0, 4))
42
- print(value.to_hex) # 0x3
43
-
44
- # Write 5 bits at offset (2 bytes, 3 bits)
45
- bits_set(buf, InfoSize(2, 3), InfoSize(0, 5), 0b10101)
46
- print(buf.hex()) # 12345578
47
-
48
- ```
49
-
50
- ## sltcore.type.InfoSize
51
-
52
- InfoSize is a type that represents offsets and sizes in a unified way.
53
- It supports addition and subtraction, and stores both byte and bit components.
54
-
55
- - byte: the byte component
56
- - bit: the bit component (0–7)
57
-
58
- always normalized so that bit < 8
59
-
60
- It is used for both offset and size, allowing consistent structural layout definitions.
61
-
62
- ## sltcore.type.Info
63
-
64
- Info stores an InfoSize and a raw integer value.
65
-
66
- - The value returned by bits_get is an Info instance
67
- - The value passed to bits_set is also an Info instance
68
-
69
- This allows higher‑level code to treat extracted fields as structured units rather than plain integers.
70
-
71
- ## sltcore.bits.bits_get
72
-
73
- bits_get extracts a field from a bytearray using an offset and size, and returns an Info object.
74
-
75
- Input:
76
-
77
- - bytearray buffer
78
- - InfoSize offset
79
- - InfoSize size
80
-
81
- Output:
82
-
83
- - Info containing the extracted value and its size
84
-
85
- ## sltcore.bits.bits_set
86
-
87
- bits_set writes a value into a bytearray at the specified offset.
88
-
89
- Input:
90
-
91
- - bytearray buffer
92
- - InfoSize offset
93
- - Info value (which includes its size)
94
-
95
- The function masks and replaces the target bit range inside the buffer.
96
-
97
- ## Documentation
98
-
99
- For detailed usage, examples, and parameter descriptions, refer to the docstrings via:
100
-
101
- python
102
-
103
- - help(sltcore.type.InfoSize)
104
- - help(sltcore.type.Info)
105
- - help(sltcore.bits.bits_get)
106
- - help(sltcore.bits.bits_set)
sltcore-0.2.1/README.md DELETED
@@ -1,91 +0,0 @@
1
- # StructLayoutToolkitCore
2
-
3
- stlcore is a minimal, high‑cohesion core library for bit‑accurate binary slicing. It provides the fundamental primitives (bits_get, bits_set, InfoSize) required to build struct layout analyzers, binary editors, protocol inspectors, and low‑level testing tools. Designed for clarity, correctness, and composability.
4
-
5
- ## What You Can Do After Installing sltcore
6
-
7
- sltcore provides a minimal and consistent bit-level abstraction layer for building higher‑level tools such as binary editors, protocol analyzers, and structured layout systems.
8
-
9
- After installing the package, you can:
10
-
11
- - Extract arbitrary bit ranges from a bytearray using bits_get
12
- - Write arbitrary bit ranges into a bytearray using bits_set
13
- - Represent sizes and offsets uniformly with InfoSize
14
- - Build structured binary layouts on top of a stable bit‑operation core
15
-
16
- ## Quick Examples: bits_get / bits_set
17
-
18
- ```python
19
-
20
- from sltcore.types import InfoSize, Info
21
- from sltcore.bits import bits_get, bits_set
22
-
23
- buf = bytearray(b"\x12\x34\x56\x78")
24
-
25
- # Extract 4 bits at offset (1 byte, 0 bits)
26
- value = bits_get(buf, InfoSize(1, 0), InfoSize(0, 4))
27
- print(value.to_hex) # 0x3
28
-
29
- # Write 5 bits at offset (2 bytes, 3 bits)
30
- bits_set(buf, InfoSize(2, 3), InfoSize(0, 5), 0b10101)
31
- print(buf.hex()) # 12345578
32
-
33
- ```
34
-
35
- ## sltcore.type.InfoSize
36
-
37
- InfoSize is a type that represents offsets and sizes in a unified way.
38
- It supports addition and subtraction, and stores both byte and bit components.
39
-
40
- - byte: the byte component
41
- - bit: the bit component (0–7)
42
-
43
- always normalized so that bit < 8
44
-
45
- It is used for both offset and size, allowing consistent structural layout definitions.
46
-
47
- ## sltcore.type.Info
48
-
49
- Info stores an InfoSize and a raw integer value.
50
-
51
- - The value returned by bits_get is an Info instance
52
- - The value passed to bits_set is also an Info instance
53
-
54
- This allows higher‑level code to treat extracted fields as structured units rather than plain integers.
55
-
56
- ## sltcore.bits.bits_get
57
-
58
- bits_get extracts a field from a bytearray using an offset and size, and returns an Info object.
59
-
60
- Input:
61
-
62
- - bytearray buffer
63
- - InfoSize offset
64
- - InfoSize size
65
-
66
- Output:
67
-
68
- - Info containing the extracted value and its size
69
-
70
- ## sltcore.bits.bits_set
71
-
72
- bits_set writes a value into a bytearray at the specified offset.
73
-
74
- Input:
75
-
76
- - bytearray buffer
77
- - InfoSize offset
78
- - Info value (which includes its size)
79
-
80
- The function masks and replaces the target bit range inside the buffer.
81
-
82
- ## Documentation
83
-
84
- For detailed usage, examples, and parameter descriptions, refer to the docstrings via:
85
-
86
- python
87
-
88
- - help(sltcore.type.InfoSize)
89
- - help(sltcore.type.Info)
90
- - help(sltcore.bits.bits_get)
91
- - help(sltcore.bits.bits_set)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes