Standard Rust core types implementations for Python.
Project description
sain
a dependency-free library which implements a few of Rust's core crates purely in Python.
It offers a few of the core Rust features such as Vec<T>
, Result<T, E>
, Option<T>
and more. See the equivalent type section below.
a few std
types are implemented. Check the project documentation
Install
You'll need Python 3.10 or higher.
PyPI
pip install sain
Overview
More examples in examples
no try/except
Rust doesn't have exception, But Option<T>
which handles None's, and Result<T, E>
for returning and propagating errors.
we can easily achieve the same results in Python
from __future__ import annotations
from sain import Option, Result, Ok, Err
from sain.collections import Vec, Bytes
from sain.convert import Into
from dataclasses import dataclass, field
# A chunk of data. the from protocol allows users to convert the chunk into bytes.
# similar to Rust's Into trait.
@dataclass
class Chunk(Into[bytes]):
tag: str
data: Bytes
# convert a chunk into bytes.
# in Rust, this consumes `self`, But in Python it copies it.
def into(self) -> bytes:
return self.data.to_bytes()
@dataclass
class BlobStore:
pos: int
# A buffer that contains chunks of bytes over which we might
# lazily load from somewhere. This buffer can hold up to 1024 chunks.
buffer: Vec[Chunk] = field(default_factory=lambda: Vec[Chunk].with_capacity(1024))
def put(self, tag: str, data: bytes) -> Result[None, str]:
chunk = Chunk(tag, Bytes.from_bytes(data))
# push_within_capacity returns `Result[None, Chunk]`.
# It returns the chunk that got failed to be pushed,
# we try to push if there's space, mapping the error to
# a string.
return self.buffer.push_within_capacity(chunk).map_err(
lambda chunk: "No more capacity to push chunk: " + str(chunk)
)
def next_chunk(self) -> Option[Chunk]:
chunk = self.buffer.get(self.pos)
self.pos += 1
return chunk
def main() -> None:
blobs = BlobStore(0)
# upload a blob matching any errors.
match blobs.put("c1", b"first chunk"):
case Ok(_):
print("chunk pushed succefully.")
case Err(why):
print(why)
# or just
blobs.put("c2", b"second chunk").unwrap()
# Read back the chunks, and map it to string.
# In rust, you would do something similar to
# * while let Some(chunk) = option.map(String::from_utf8_lossy) { ... } *
while (chunk := blobs.next_chunk()).is_some():
print(chunk.map(Chunk.into))
# use an iterator over the chunks
for pos, chunk in blobs.buffer.iter().enumerate():
print(pos, chunk.data)
built-in types
name in Rust | name in Python | note | restrictions |
---|---|---|---|
Option<T>, Some(T), None | Option[T], Some(T), Some(None) | Some(None) has the same layout as None in Rust |
|
Result<T, E>, Ok(T), Err(E) | Result[T, E], Ok(T), Err(E) | ||
Vec<T> | Vec[T] | ||
HashMap<K, V> | HashMap[K, V] | ||
bytes::Bytes | Bytes | ||
LazyLock<T> | Lazy[T] | ||
OnceLock<T> | Once[T] | ||
Box<T> | Box[T] | this isn't a heap box, See | |
MaybeUninit<T> | MaybeUninit[T] | they serve the same purpose, but slightly different | |
&dyn Default | Default[T] | ||
&dyn Error | Error | ||
&dyn Iterator<T> | Iterator[T] | ||
Iter<'a, T> | Iter[T] | collections called by .iter() are built from this type |
|
iter::once::<T>() | iter.once[T] | ||
iter::empty::<T>() | iter.empty[T] | ||
iter::repeat::<T>() | iter.repeat[T] | ||
cfg!() | cfg() | runtime cfg, not all predictions are supported | |
#[cfg_attr] | @cfg_attr() | runtime cfg, not all predictions are supported | |
#[doc] | @doc() | the docs get generated at runtime | |
todo!() | todo() | ||
#[deprecated] | @deprecated() | will get removed when it get stabilized in warnings in Python 3.13 |
|
unimplemented!() | @unimplemented() |
Notes
Since Rust is a compiled language, Whatever predict in cfg
and cfg_attr
returns False will not compile.
But there's no such thing as this in Python, So RuntimeError
will be raised and whatever was predicated will not run.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file sain-1.2.0.tar.gz
.
File metadata
- Download URL: sain-1.2.0.tar.gz
- Upload date:
- Size: 46.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.12.5 Linux/6.5.0-1025-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 45ffb3b4ab55b0a76793596c389837e44a3d05b11408b9644481d6acbeb96895 |
|
MD5 | ed4dc09d458ed688bdc2a409c6f0ee26 |
|
BLAKE2b-256 | 49f490661061ca6a10c602c5f02b7b2c7206bd2b741aace1d34ca27335d46380 |
File details
Details for the file sain-1.2.0-py2.py3-none-any.whl
.
File metadata
- Download URL: sain-1.2.0-py2.py3-none-any.whl
- Upload date:
- Size: 69.0 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: poetry/1.7.1 CPython/3.12.5 Linux/6.5.0-1025-azure
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | c335868ecbcfadccc0414f7ecc96b91387ca15a92d1b15c0211adb6c07f3e422 |
|
MD5 | 28fbdd76d6f0fea63567fe5c7d1a594c |
|
BLAKE2b-256 | 107f5dc6c5d3cb5f0505c26d81396ddf3d9d94b0f8b115c0f4441e046ac49832 |