3 releases

0.1.2 Oct 20, 2022
0.1.1 Aug 23, 2022
0.1.0 Aug 1, 2022

#1207 in Rust patterns

Download history 6766/week @ 2023-11-29 6884/week @ 2023-12-06 5264/week @ 2023-12-13 3244/week @ 2023-12-20 2810/week @ 2023-12-27 4018/week @ 2024-01-03 3544/week @ 2024-01-10 3436/week @ 2024-01-17 3322/week @ 2024-01-24 5075/week @ 2024-01-31 4384/week @ 2024-02-07 4511/week @ 2024-02-14 5686/week @ 2024-02-21 4824/week @ 2024-02-28 7338/week @ 2024-03-06 5989/week @ 2024-03-13

24,452 downloads per month
Used in 8 crates (via strck_ident)

MIT license

28KB
379 lines

github-img crates-img docs-img

Checked owned and borrowed strings.

Overview

The Rust standard library provides the String and str types, which wrap Vec<u8> and [u8] respectively, with the invariant that the contents are valid UTF-8.

This crate abstracts the idea of type-level invariants on strings by introducing the immutable Check and Ck types, where the invariants are determined by a generic Invariant type parameter. Implementing the Invariant trait is left to other crates, such as strck_ident.

"strck" comes from "str check", similar to how rustc has typeck and borrowck for type check and borrow check respectively.

See the documentation for more details.

Motivation

Libraries working with string-like types with certain properties, like identifiers, quickly become confusing as &str and String begin to pollute type signatures everywhere. One solution is to manually implement an owned checked string type like syn::Ident to disambiguate the type signatures and validate the string. The downside is that new values cannot be created without allocation, which is unnecessary when only a borrowed version is required.

strck solves this issue by providing a checked borrowed string type, Ck, alongside a checked owned string type, Check. These serve as thin wrappers around str and String[^1] respectively, and prove at the type level that the contents satisfy the Invariant that the wrapper is generic over.

[^1]: Check can actually be backed by any 'static + AsRef<str> type, but String is the default.

Use cases

Checked strings without allocating

The main benefit strck offers is validating borrowed strings via the Ck type without having to allocate in the result.

use strck_ident::{Ck, IntoCk, rust::RustIdent};

let this_ident: &Ck<RustIdent> = "this".ck().unwrap();

Checked zero-copy deserialization

When the serde feature flag is enabled, Cks can be used to perform checked zero-copy deserialization, which requires the #[serde(borrow)] attribute.

use strck_ident::{Ck, unicode::UnicodeIdent};

#[derive(Serialize, Deserialize)]
struct Player<'a> {
    #[serde(borrow)]
    username: &'a Ck<UnicodeIdent>,
    level: u32,
}

Note that this code sample explicitly uses Ck<UnicodeIdent> to demonstrate that the type is a Ck. However, strck_ident provides Ident as an alias for Ck<UnicodeIdent>, which should be used in practice.

Infallible parsing

For types where string validation is relatively cheap but parsing is costly and fallible, strck can be used with a custom Invariant as an input to make an infallible parsing function.

Postfix construction with IntoCk and IntoCheck

This crate exposes two helper traits, IntoCk and IntoCheck. When in scope, the .ck() and .check() functions can be used to create Cks and Checks respectively:

use strck_ident::{IntoCheck, IntoCk, unicode::UnicodeIdent};

let this_ident = "this".ck::<UnicodeIdent>().unwrap();
let this_foo_ident = format!("{}_foo", this_ident).check::<UnicodeIdent>().unwrap();

Documentation

See the crate-level documentation for more details.

Dependencies

~175KB