Skip to main content

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

sain-1.2.0.tar.gz (46.2 kB view details)

Uploaded Source

Built Distribution

sain-1.2.0-py2.py3-none-any.whl (69.0 kB view details)

Uploaded Python 2 Python 3

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

Hashes for sain-1.2.0.tar.gz
Algorithm Hash digest
SHA256 45ffb3b4ab55b0a76793596c389837e44a3d05b11408b9644481d6acbeb96895
MD5 ed4dc09d458ed688bdc2a409c6f0ee26
BLAKE2b-256 49f490661061ca6a10c602c5f02b7b2c7206bd2b741aace1d34ca27335d46380

See more details on using hashes here.

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

Hashes for sain-1.2.0-py2.py3-none-any.whl
Algorithm Hash digest
SHA256 c335868ecbcfadccc0414f7ecc96b91387ca15a92d1b15c0211adb6c07f3e422
MD5 28fbdd76d6f0fea63567fe5c7d1a594c
BLAKE2b-256 107f5dc6c5d3cb5f0505c26d81396ddf3d9d94b0f8b115c0f4441e046ac49832

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page