Metadata-Version: 2.4
Name: ipickl
Version: 1.1.0
Summary: Minimal integer-based serialisation protocol with cross-language parity
Author-email: "G. Eckersley" <g.eckersley@ieee.org>
License: MIT License
        
        Copyright (c) 2025 G. Eckersley
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
License-File: LICENSE
Keywords: cross-language,embedded,protocol,serialisation,varint
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: System :: Networking
Requires-Python: >=3.8
Description-Content-Type: text/markdown

# ipickl

A minimal, integer-based serialisation protocol designed for simplicity, correctness, and cross-language parity.

## Philosophy

ipickl represents all structured data as sequences of non-negative integers. There are no raw byte strings, no floating point, no platform-specific encodings. This makes the protocol naturally portable across languages and well-suited to embedded systems where simplicity and correctness matter.

## Features

- **Pure integer representation** — all data reduced to integer sequences
- **Varint encoding** — compact wire format, efficient for small values
- **Guard-based integrity** — structural guards provide framing and error detection without separate CRC fields
- **No dependencies** — pure Python, zero imports required for core functionality
- **Cross-language** — reference implementations in Python, JavaScript, and C
- **Embedded-friendly** — C implementation runs on bare metal (tested on RP2040)

## Installation

```bash
pip install ipickl
```

## Quick Start

```python
import ipickl

# Encode a Python value to bytes
data = ipickl.encode({'cmd': 'shift_dr', 'bits': 32, 'data': 0xDEADBEEF})

# Decode bytes back to a Python value
value = ipickl.decode(data)
```

## Supported Types

| Python type | ipickl encoding |
|-------------|----------------|
| `int` (positive) | T_POS_INT + magnitude |
| `int` (negative) | T_NEG_INT + magnitude |
| `str` | T_STR + guarded codepoints |
| `list`, `tuple` | T_SEQ + guarded elements |
| `dict` | T_DICT + guarded key/value pairs |
| `None` | T_NONE |
| `Fraction` | T_FRAC_POS / T_FRAC_NEG + numerator + denominator |
| `bool` | encoded as 0 or 1 integer |

Note: `float` is not supported by design. Use `fractions.Fraction` for exact rational arithmetic.

## Architecture

ipickl uses a layered representation model:

```
rep4  — Python objects (program data)
  ↕  Stage-1: structural encoding
rep3  — integer sequence (tags, magnitudes, guards)
  ↕  Stage-2: varint encoding
rep1  — bytes (wire format)
```

### Guards

Structured types (strings, lists, dicts) are wrapped in guard blocks:

```
TAG  GUARD  B1  B2  ...  Bk  GUARD
```

where `GUARD = sum(body integers) + 1`. A mismatch between leading and trailing guard values signals a structural error. This provides integrity checking and self-delimiting structure without length prefixes.

### Packet framing over TCP/serial

ipickl does not define packet boundaries — this is a transport concern. Over TCP the v1.0 packet frame wraps a payload with a checksum-derived guard:

```
Packet = Guard | Payload | Guard
Guard  = checksum(Payload) + 1
```

## Streaming

For incremental decoding over TCP or serial streams:

```python
decoder = ipickl.UnitStreamDecoder(width=8)
decoder.start_stream()

for byte in incoming:
    decoder.accept_unit(byte)

# At packet boundary:
value = ipickl.decode_stage1(decoder.int_buffer)
decoder.start_stream()
```

## Comparison with alternatives

| Feature | ipickl | pickle | MessagePack | CBOR |
|---------|--------|--------|-------------|------|
| Pure integer wire format | ✓ | ✗ | ✗ | ✗ |
| No dependencies | ✓ | ✓ | ✗ | ✗ |
| Embedded C implementation | ✓ | ✗ | partial | partial |
| Guard-based integrity | ✓ | ✗ | ✗ | ✗ |
| Cross-language parity | ✓ | ✗ | ✓ | ✓ |
| Float support | ✗ | ✓ | ✓ | ✓ |

## Implementations

| Language | Status |
|----------|--------|
| Python | Reference implementation (this package) |
| JavaScript | Available — contact author |
| C | Available — contact author (no large integer support) |

JavaScript and C implementations are freely available on request. Contact g.eckersley@ieee.org.

## Licence

MIT
