├── CHANGELOG.md
├── .gitignore
├── .github
├── assets
│ ├── logo.png
│ ├── volo-feishu-dev-group.png
│ └── volo-feishu-user-group.png
├── workflows
│ ├── dependency-review.yaml
│ ├── security.yaml
│ └── ci.yaml
├── PULL_REQUEST_TEMPLATE.md
└── ISSUE_TEMPLATE
│ ├── feature_request.md
│ └── bug_report.md
├── utils
├── Cargo.toml
├── src
│ └── main.rs
├── README.md
├── faststr_gdb.py
└── faststr_lldb.py
├── rustfmt.toml
├── SUPPORT.md
├── LICENSE-MIT
├── src
├── sqlx_mysql.rs
├── rkyv.rs
├── ts_rs.rs
├── sqlx_postgres.rs
├── redis.rs
├── serde.rs
├── sea_orm.rs
└── lib.rs
├── benches
└── faststr.rs
├── SECURITY.md
├── Cargo.toml
├── CODE_OF_CONDUCT.md
├── README.md
├── LICENSE-APACHE
├── CONTRIBUTING.md
└── Cargo.lock
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | .idea
3 | /target
4 |
--------------------------------------------------------------------------------
/.github/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/volo-rs/faststr/HEAD/.github/assets/logo.png
--------------------------------------------------------------------------------
/.github/assets/volo-feishu-dev-group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/volo-rs/faststr/HEAD/.github/assets/volo-feishu-dev-group.png
--------------------------------------------------------------------------------
/.github/assets/volo-feishu-user-group.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/volo-rs/faststr/HEAD/.github/assets/volo-feishu-user-group.png
--------------------------------------------------------------------------------
/utils/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "debugger-example"
3 | version = "0.1.0"
4 | edition = "2024"
5 |
6 | [dependencies]
7 | faststr = { path = ".." }
8 |
--------------------------------------------------------------------------------
/rustfmt.toml:
--------------------------------------------------------------------------------
1 | comment_width = 100
2 | edition = "2021"
3 | format_code_in_doc_comments = true
4 | format_strings = true
5 | group_imports = "StdExternalCrate"
6 | imports_granularity = "Crate"
7 | normalize_comments = true
8 | normalize_doc_attributes = true
9 | wrap_comments = true
10 |
11 |
--------------------------------------------------------------------------------
/.github/workflows/dependency-review.yaml:
--------------------------------------------------------------------------------
1 | name: 'Dependency Review'
2 | on: [pull_request]
3 |
4 | permissions:
5 | contents: read
6 |
7 | jobs:
8 | dependency-review:
9 | runs-on: [self-hosted, Linux, amd64]
10 | steps:
11 | - name: 'Checkout Repository'
12 | uses: actions/checkout@v4
13 | - name: 'Dependency Review'
14 | uses: actions/dependency-review-action@v1
15 |
--------------------------------------------------------------------------------
/.github/workflows/security.yaml:
--------------------------------------------------------------------------------
1 | name: "Security Audit"
2 | on:
3 | pull_request:
4 | push:
5 | paths:
6 | - "**/Cargo.toml"
7 | - "**/Cargo.lock"
8 | jobs:
9 | security-audit:
10 | runs-on: [self-hosted, Linux, amd64]
11 | steps:
12 | - uses: actions/checkout@v4
13 | - uses: dtolnay/rust-toolchain@stable
14 | - uses: actions-rs/audit-check@v1
15 | with:
16 | token: ${{ secrets.GITHUB_TOKEN }}
17 |
--------------------------------------------------------------------------------
/SUPPORT.md:
--------------------------------------------------------------------------------
1 | # Support
2 |
3 | There are many ways to get help with your issues.
4 |
5 | - Open a GitHub issue in the respective GitHub repository.
6 | - Feishu: Scan the QR code below with [Feishu](https://www.feishu.cn/) or [click this link](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=b34v5470-8e4d-4c7d-bf50-8b2917af026b) to join our CloudWeGo Volo user group.
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
9 |
10 | ## Motivation
11 |
12 |
17 |
18 | ## Solution
19 |
20 |
24 |
--------------------------------------------------------------------------------
/utils/src/main.rs:
--------------------------------------------------------------------------------
1 | use faststr::FastStr;
2 |
3 | const LONG_STRING: &str = "1145141919810114514191981011451419198101145141919810";
4 | const SHORT_STRING: &str = "Hello, World";
5 |
6 | fn main() {
7 | let s1 = FastStr::empty();
8 | let s2 = FastStr::from_string(LONG_STRING.to_string());
9 | let s3 = FastStr::from_arc_str(std::sync::Arc::from(LONG_STRING));
10 | let s4 = FastStr::from_arc_string(std::sync::Arc::new(LONG_STRING.to_string()).clone());
11 | let s5 = FastStr::from_static_str(LONG_STRING);
12 | let s6 = FastStr::from_string(SHORT_STRING.to_string());
13 |
14 | println!("{s1:?}");
15 | println!("{s2:?}");
16 | println!("{s3:?}");
17 | println!("{s4:?}");
18 | println!("{s5:?}");
19 | println!("{s6:?}");
20 | }
21 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 💡 Feature Request
3 | about: I have a suggestion (and may want to implement it 🙂)!
4 | ---
5 |
6 | ## Feature Request
7 |
8 | ### Crates
9 |
10 |
14 |
15 | ### Motivation
16 |
17 |
20 |
21 | ### Proposal
22 |
23 |
27 |
28 | ### Alternatives
29 |
30 |
35 |
--------------------------------------------------------------------------------
/LICENSE-MIT:
--------------------------------------------------------------------------------
1 | Copyright (c) 2022 Volo Contributors
2 |
3 | Permission is hereby granted, free of charge, to any
4 | person obtaining a copy of this software and associated
5 | documentation files (the "Software"), to deal in the
6 | Software without restriction, including without
7 | limitation the rights to use, copy, modify, merge,
8 | publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software
10 | is furnished to do so, subject to the following
11 | conditions:
12 |
13 | The above copyright notice and this permission notice
14 | shall be included in all copies or substantial portions
15 | of the Software.
16 |
17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
18 | ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
19 | TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
20 | PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
21 | SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
22 | CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
23 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
24 | IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
25 | DEALINGS IN THE SOFTWARE.
26 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: 🐛 Bug Report
3 | about: If something isn't working as expected 🤔.
4 | ---
5 |
6 | ## Bug Report
7 |
8 |
13 |
14 | ### Version
15 |
16 |
27 |
28 | ### Platform
29 |
30 |
33 |
34 | ### Crates
35 |
36 |
40 |
41 | ### Description
42 |
43 |
59 |
--------------------------------------------------------------------------------
/src/sqlx_mysql.rs:
--------------------------------------------------------------------------------
1 | use sqlx::{encode::IsNull, error::BoxDynError, Decode, Encode, Type};
2 | use sqlx_mysql::{MySql, MySqlTypeInfo, MySqlValueRef};
3 |
4 | use crate::FastStr;
5 |
6 | impl Type for FastStr {
7 | fn type_info() -> MySqlTypeInfo {
8 | >::type_info()
9 | }
10 |
11 | fn compatible(ty: &MySqlTypeInfo) -> bool {
12 | >::compatible(ty)
13 | }
14 | }
15 |
16 | impl<'r> Decode<'r, MySql> for FastStr {
17 | fn decode(value: MySqlValueRef<'r>) -> Result {
18 | #[cfg(not(feature = "sqlx-mysql-unsafe"))]
19 | {
20 | let b = <&[u8] as Decode>::decode(value)?;
21 | return simdutf8::basic::from_utf8(b)
22 | .map_err(|e| Box::new(e) as BoxDynError)
23 | .map(FastStr::new);
24 | }
25 | #[cfg(feature = "sqlx-mysql-unsafe")]
26 | unsafe {
27 | return <&[u8] as Decode>::decode(value)
28 | .map(|b| FastStr::new(std::str::from_utf8_unchecked(b)));
29 | }
30 | }
31 | }
32 |
33 | impl Encode<'_, MySql> for FastStr {
34 | fn encode_by_ref(&self, buf: &mut Vec) -> Result {
35 | <&str as Encode>::encode(self.as_str(), buf)
36 | }
37 | fn size_hint(&self) -> usize {
38 | <&str as Encode>::size_hint(&self.as_str())
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/rkyv.rs:
--------------------------------------------------------------------------------
1 | #[cfg(not(feature = "std"))]
2 | use alloc::string::String;
3 |
4 | use rancor::{Fallible, Source};
5 | use rkyv::{
6 | ser::{Allocator, Writer},
7 | string::{ArchivedString, StringResolver},
8 | *,
9 | };
10 |
11 | use super::FastStr;
12 |
13 | impl Archive for FastStr {
14 | type Archived = ArchivedString;
15 | type Resolver = StringResolver;
16 |
17 | fn resolve(&self, resolver: Self::Resolver, out: Place) {
18 | ArchivedString::resolve_from_str(self, resolver, out);
19 | }
20 | }
21 |
22 | impl Serialize for FastStr
23 | where
24 | S: Fallible + Allocator + Writer + ?Sized,
25 | S::Error: Source,
26 | {
27 | fn serialize(&self, serializer: &mut S) -> Result {
28 | ArchivedString::serialize_from_str(self, serializer)
29 | }
30 | }
31 |
32 | impl Deserialize for ArchivedString {
33 | fn deserialize(&self, _deserializer: &mut D) -> Result {
34 | Ok(FastStr::new(self.as_str()))
35 | }
36 | }
37 |
38 | impl PartialEq for ArchivedString {
39 | fn eq(&self, other: &FastStr) -> bool {
40 | other.as_str() == self.as_str()
41 | }
42 | }
43 |
44 | impl PartialOrd for ArchivedString {
45 | fn partial_cmp(&self, other: &FastStr) -> Option<::core::cmp::Ordering> {
46 | Some(self.as_str().cmp(other.as_str()))
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/ts_rs.rs:
--------------------------------------------------------------------------------
1 | use crate::FastStr;
2 |
3 | impl ts_rs::TS for FastStr {
4 | type OptionInnerType = Self;
5 | type WithoutGenerics = Self;
6 |
7 | fn name() -> String {
8 | "string".to_owned()
9 | }
10 | fn inline() -> String {
11 | ::name()
12 | }
13 | /// This function is expected to panic because primitive types cannot be flattened.
14 | fn inline_flattened() -> String {
15 | panic!("{} cannot be flattened", ::name())
16 | }
17 | /// This function is expected to panic because primitive types cannot be declared.
18 | fn decl() -> String {
19 | panic!("{} cannot be declared", ::name())
20 | }
21 | /// Same as `decl` if the type is not generic.
22 | fn decl_concrete() -> String {
23 | panic!("{} cannot be declared", ::name())
24 | }
25 | }
26 |
27 | #[test]
28 | fn test_ts_rs() {
29 | #[derive(ts_rs::TS)]
30 | struct Nested {
31 | #[allow(unused)]
32 | #[ts(rename = "nested_id")]
33 | id: FastStr,
34 | }
35 | #[derive(ts_rs::TS)]
36 | struct Test {
37 | #[allow(unused)]
38 | #[ts(optional)]
39 | id: Option,
40 | #[allow(unused)]
41 | #[ts(flatten)]
42 | nested: Nested,
43 | }
44 |
45 | assert_eq!(
46 | ::decl(),
47 | "type Test = { id?: string, nested_id: string, };"
48 | );
49 | }
50 |
--------------------------------------------------------------------------------
/src/sqlx_postgres.rs:
--------------------------------------------------------------------------------
1 | use sqlx::{encode::IsNull, error::BoxDynError, Decode, Encode, Type};
2 | use sqlx_postgres::{PgTypeInfo, PgValueRef, Postgres};
3 |
4 | use crate::FastStr;
5 |
6 | impl Type for FastStr {
7 | fn type_info() -> PgTypeInfo {
8 | >::type_info()
9 | }
10 |
11 | fn compatible(ty: &PgTypeInfo) -> bool {
12 | >::compatible(ty)
13 | }
14 | }
15 | impl<'r> Decode<'r, Postgres> for FastStr {
16 | fn decode(value: PgValueRef<'r>) -> Result {
17 | #[cfg(not(feature = "sqlx-postgres-unsafe"))]
18 | {
19 | let b = <&[u8] as Decode>::decode(value)?;
20 | return simdutf8::basic::from_utf8(b)
21 | .map_err(|e| Box::new(e) as BoxDynError)
22 | .map(FastStr::new);
23 | }
24 | #[cfg(feature = "sqlx-postgres-unsafe")]
25 | unsafe {
26 | return <&[u8] as Decode>::decode(value)
27 | .map(|b| FastStr::new(std::str::from_utf8_unchecked(b)));
28 | }
29 | }
30 | }
31 |
32 | impl Encode<'_, Postgres> for FastStr {
33 | fn encode_by_ref(
34 | &self,
35 | buf: &mut ::ArgumentBuffer<'_>,
36 | ) -> Result {
37 | <&str as Encode>::encode(self.as_str(), buf)
38 | }
39 | fn size_hint(&self) -> usize {
40 | <&str as Encode>::size_hint(&self.as_str())
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/benches/faststr.rs:
--------------------------------------------------------------------------------
1 | use bytes::Bytes;
2 | use criterion::{black_box, criterion_group, criterion_main, Criterion};
3 | use faststr::FastStr;
4 |
5 | fn criterion_benchmark(c: &mut Criterion) {
6 | let s = FastStr::empty();
7 | c.bench_function("empty faststr", |b| b.iter(|| black_box(s.clone())));
8 | let s = String::new();
9 | c.bench_function("empty string", |b| b.iter(|| black_box(s.clone())));
10 |
11 | let s = FastStr::from("Hello, world!");
12 | c.bench_function("static faststr", |b| b.iter(|| black_box(s.clone())));
13 | #[allow(deprecated)]
14 | let s = FastStr::new_inline("Hello, world!");
15 | c.bench_function("inline faststr", |b| b.iter(|| black_box(s.clone())));
16 | let s = String::from("Hello, world!");
17 | c.bench_function("string hello world", |b| b.iter(|| black_box(s.clone())));
18 |
19 | for size in [512, 4 * 1024, 16 * 1024, 64 * 1024, 512 * 1024, 1024 * 1024] {
20 | let s = FastStr::from_bytes(Bytes::from("a".repeat(size)));
21 | let _s1 = black_box(s.clone());
22 | let _s2 = black_box(s.clone());
23 | c.bench_function(format!("{}B faststr", size).as_str(), |b| {
24 | b.iter(|| black_box(s.clone()))
25 | });
26 | drop(_s1);
27 | drop(_s2);
28 | let s = "a".repeat(size);
29 | c.bench_function(format!("{}B string", size).as_str(), |b| {
30 | b.iter(|| black_box(s.clone()))
31 | });
32 | }
33 | }
34 |
35 | criterion_group!(benches, criterion_benchmark);
36 | criterion_main!(benches);
37 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | # Security Policies and Procedures
2 |
3 | This document outlines security procedures and general policies for CloudWeGo.
4 |
5 | * [Reporting a Bug](#reporting-a-bug)
6 | * [Disclosure Policy](#disclosure-policy)
7 | * [Comments on this Policy](#comments-on-this-policy)
8 |
9 | ## Reporting a Bug
10 |
11 | The CloudWeGo team and community take all security bugs in CloudWeGo seriously.
12 | Thank you for improving the security of CloudWeGo. We appreciate your efforts and
13 | responsible disclosure and will make every effort to acknowledge your
14 | contributions.
15 |
16 | Report security bugs by emailing the lead maintainer at [security@cloudwego.io](mailto:security@cloudwego.io).
17 |
18 | The lead maintainer will acknowledge your email within 48 hours, and will send a
19 | more detailed response within 48 hours indicating the next steps in handling
20 | your report. After the initial reply to your report, the security team will
21 | endeavor to keep you informed of the progress towards a fix and full
22 | announcement, and may ask for additional information or guidance.
23 |
24 | Report security bugs in third-party modules to the person or team maintaining
25 | the module.
26 |
27 | ## Disclosure Policy
28 |
29 | When the security team receives a security bug report, they will assign it to a
30 | primary handler. This person will coordinate the fix and release process,
31 | involving the following steps:
32 |
33 | * Confirm the problem and determine the affected versions.
34 | * Audit code to find any potential similar problems.
35 | * Prepare fixes for all releases still under maintenance. These fixes will be
36 | released as fast as possible to npm.
37 |
38 | ## Comments on this Policy
39 |
40 | If you have suggestions on how this process could be improved please submit a
41 | pull request.
42 |
--------------------------------------------------------------------------------
/Cargo.toml:
--------------------------------------------------------------------------------
1 | [package]
2 | name = "faststr"
3 | version = "0.2.32"
4 | authors = ["Volo Team "]
5 | edition = "2021"
6 | description = "Faststr is a string library that reduces the cost of clone."
7 | repository = "https://github.com/volo-rs/faststr"
8 | license = "MIT OR Apache-2.0"
9 | readme = "README.md"
10 | keywords = ["string", "str", "volo"]
11 |
12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
13 |
14 | [dependencies]
15 | bytes = { version = "1", default-features = false }
16 | serde = { version = "1", optional = true, default-features = false }
17 | simdutf8 = { version = "0.1", default-features = false, features = [
18 | "aarch64_neon",
19 | ] }
20 | redis = { version = "1.0", optional = true, default-features = false, features = [
21 | "num-bigint",
22 | ] }
23 | itoa = { version = "1", optional = true }
24 | ryu = { version = "1", optional = true }
25 | rkyv = { version = "0.8", optional = true, default-features = false }
26 | sqlx = { version = "0.8", optional = true, default-features = false }
27 | sqlx-mysql = { version = "0.8", optional = true, default-features = false }
28 | sqlx-postgres = { version = "0.8.6", optional = true, default-features = false }
29 | ts-rs = { version = "11", optional = true, default-features = false }
30 | sea-orm = { version = "1.1", optional = true, default-features = false }
31 |
32 | [features]
33 | default = ["std"]
34 | std = ["bytes/std", "simdutf8/std", "serde?/std", "rkyv?/std"]
35 | serde = ["serde/alloc"]
36 | serde-unsafe = ["serde"]
37 | redis = ["std", "dep:redis", "itoa", "ryu"]
38 | redis-unsafe = ["redis"]
39 | rkyv = ["rkyv/alloc"]
40 | sqlx-mysql = ["std", "dep:sqlx", "dep:sqlx-mysql"]
41 | sqlx-mysql-unsafe = ["sqlx-mysql"]
42 | sqlx-postgres = ["std", "dep:sqlx", "dep:sqlx-postgres"]
43 | sqlx-postgres-unsafe = ["sqlx-postgres"]
44 | ts-rs = ["std", "dep:ts-rs"]
45 | sea-orm = ["std", "dep:sea-orm", "itoa"]
46 |
47 | [dev-dependencies]
48 | static_assertions = { version = "1" }
49 | criterion = { version = "0.7", features = ["html_reports"] }
50 |
51 | # For sea-orm integration tests
52 | sea-orm = { version = "1.1", features = ["macros", "mock"] }
53 | tokio = { version = "1", features = ["rt", "macros"] }
54 |
55 | [workspace]
56 | members = [".", "utils"]
57 |
58 | [[bench]]
59 | name = "faststr"
60 | harness = false
61 |
62 | [profile.bench]
63 | debug = true
64 | lto = true
65 | opt-level = 3
66 |
--------------------------------------------------------------------------------
/src/redis.rs:
--------------------------------------------------------------------------------
1 | impl redis::ToRedisArgs for crate::FastStr {
2 | fn write_redis_args(&self, out: &mut W)
3 | where
4 | W: ?Sized + redis::RedisWrite,
5 | {
6 | out.write_arg(self.as_bytes())
7 | }
8 | }
9 |
10 | impl redis::FromRedisValue for crate::FastStr {
11 | fn from_redis_value_ref(v: &redis::Value) -> Result {
12 | match v {
13 | redis::Value::Nil => Ok(Self::empty()),
14 | redis::Value::Int(v) => Ok(Self::new(itoa::Buffer::new().format(*v))),
15 | redis::Value::Okay => Ok(Self::from_static_str("OK")),
16 | #[cfg(feature = "redis-unsafe")]
17 | redis::Value::BulkString(v) => {
18 | Ok(unsafe { Self::new(std::str::from_utf8_unchecked(v)) })
19 | }
20 | #[cfg(not(feature = "redis-unsafe"))]
21 | redis::Value::BulkString(v) => Ok(Self::new(std::str::from_utf8(v)?)),
22 | redis::Value::SimpleString(v) => Ok(Self::new(v)),
23 | redis::Value::Double(v) => Ok(Self::new(ryu::Buffer::new().format(*v))),
24 | redis::Value::Boolean(v) => {
25 | Ok(Self::from_static_str(if *v { "true" } else { "false" }))
26 | }
27 | redis::Value::BigNumber(v) => Ok(Self::from_string(v.to_string())),
28 | e => Err(format!("Invalid response type:{:?}", e).into()),
29 | }
30 | }
31 |
32 | fn from_redis_value(v: redis::Value) -> Result {
33 | match v {
34 | #[cfg(feature = "redis-unsafe")]
35 | redis::Value::BulkString(v) => Ok(unsafe { Self::from_vec_u8_unchecked(v) }),
36 | #[cfg(not(feature = "redis-unsafe"))]
37 | redis::Value::BulkString(v) => Self::from_vec_u8(v).map_err(|_| "Invalid UTF8".into()),
38 | redis::Value::Nil => Ok(Self::empty()),
39 | redis::Value::Int(v) => Ok(Self::new(itoa::Buffer::new().format(v))),
40 | redis::Value::Okay => Ok(Self::from_static_str("OK")),
41 | redis::Value::SimpleString(v) => Ok(Self::from_string(v)),
42 | redis::Value::Double(v) => Ok(Self::new(ryu::Buffer::new().format(v))),
43 | redis::Value::Boolean(v) => Ok(Self::from_static_str(if v { "true" } else { "false" })),
44 | redis::Value::BigNumber(v) => Ok(Self::from_string(v.to_string())),
45 | e => Err(format!("Invalid response type:{:?}", e).into()),
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yaml:
--------------------------------------------------------------------------------
1 | name: 'CI'
2 | on:
3 | pull_request:
4 | push:
5 | branches:
6 | - main
7 |
8 | env:
9 | RUST_BACKTRACE: 1
10 | CARGO_TERM_COLOR: always
11 |
12 | jobs:
13 | ci-pass:
14 | name: CI is green
15 | runs-on: ubuntu-latest
16 | needs:
17 | - test-linux
18 | - test-linux-aarch64
19 | - test-macos
20 | - test-windows
21 | - test-no-std
22 | - lint
23 | steps:
24 | - run: exit 0
25 |
26 | test-linux:
27 | runs-on: [self-hosted, Linux, amd64]
28 |
29 | steps:
30 | - uses: actions/checkout@v4
31 | - uses: dtolnay/rust-toolchain@stable
32 | with:
33 | components: rustfmt
34 | # - uses: Swatinem/rust-cache@v1
35 | - name: Run tests
36 | run: |
37 | cargo check
38 | cargo test
39 |
40 | test-linux-aarch64:
41 | runs-on: [self-hosted, Linux, aarch64]
42 |
43 | steps:
44 | - uses: actions/checkout@v4
45 | - uses: dtolnay/rust-toolchain@stable
46 | with:
47 | components: rustfmt
48 | # - uses: Swatinem/rust-cache@v1
49 | - name: Run tests
50 | run: |
51 | cargo check
52 | cargo test
53 |
54 | test-macos:
55 | runs-on: [self-hosted, macOS]
56 |
57 | steps:
58 | - uses: actions/checkout@v4
59 | - uses: dtolnay/rust-toolchain@stable
60 | with:
61 | components: rustfmt
62 | # - uses: Swatinem/rust-cache@v1
63 | - name: Run tests
64 | run: |
65 | cargo check
66 | cargo test
67 |
68 | test-windows:
69 | runs-on: [self-hosted, Windows]
70 |
71 | steps:
72 | - uses: actions/checkout@v4
73 | - uses: dtolnay/rust-toolchain@stable
74 | with:
75 | components: rustfmt
76 | # - uses: Swatinem/rust-cache@v1
77 | - name: Run tests
78 | run: |
79 | cargo check
80 | cargo test
81 |
82 | test-no-std:
83 | runs-on: [self-hosted, Linux, amd64]
84 | strategy:
85 | matrix:
86 | target:
87 | - x86_64-unknown-none
88 | - aarch64-unknown-none
89 | steps:
90 | - uses: actions/checkout@v4
91 | - uses: dtolnay/rust-toolchain@stable
92 | with:
93 | components: rustfmt
94 | - name: Check no_std
95 | run: |
96 | rustup target add ${{ matrix.target }}
97 | cargo check --target ${{ matrix.target }} --no-default-features
98 |
99 | lint:
100 | runs-on: [self-hosted, Linux, amd64]
101 |
102 | steps:
103 | - uses: actions/checkout@v4
104 | - uses: dtolnay/rust-toolchain@stable
105 | with:
106 | components: rustfmt, clippy
107 | # - uses: Swatinem/rust-cache@v1
108 | - uses: actions-rs/clippy-check@v1
109 | with:
110 | token: ${{ secrets.GITHUB_TOKEN }}
111 | - name: Format check
112 | run: |
113 | cargo fmt -- --check
114 |
--------------------------------------------------------------------------------
/utils/README.md:
--------------------------------------------------------------------------------
1 | # Debugger Utilities
2 |
3 | ## Usage
4 |
5 | For GDB, you can download the `faststr_gdb.py` and put it in your `.gdbinit`:
6 |
7 | ```bash
8 | curl -fsSL https://github.com/volo-rs/faststr/raw/refs/heads/main/utils/faststr_gdb.py -o faststr_gdb.py
9 | echo "source $PWD/faststr_gdb.py" >> $HOME/.gdbinit
10 | ```
11 |
12 | For LLDB, you can download the `faststr_lldb.py` and put it in your `.lldbinit`:
13 |
14 | ```bash
15 | curl -fsSL https://github.com/volo-rs/faststr/raw/refs/heads/main/utils/faststr_lldb.py -o faststr_lldb.py
16 | echo "command script import $PWD/faststr_lldb.py" >> $HOME/.lldbinit
17 | ```
18 |
19 | ## Examples
20 |
21 | ### GDB
22 |
23 | ```
24 | $ cargo build -p debugger-example
25 | Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s
26 |
27 | $ gdb ../target/debug/debugger-example
28 | (gdb) break main.rs:14
29 | Breakpoint 1 at 0xd10d: file utils/src/main.rs, line 14.
30 | (gdb) run
31 | Starting program: ../target/debug/debugger-example
32 |
33 | Breakpoint 1, debugger_example::main () at utils/src/main.rs:14
34 | 14 println!("{s1:?}");
35 | (gdb) source faststr_gdb.py
36 | (gdb) print s1
37 | $1 = FastStr::Empty("")
38 | (gdb) print s2
39 | $2 = FastStr::Bytes("1145141919810114514191981011451419198101145141919810")
40 | (gdb) print s3
41 | $3 = FastStr::ArcStr("1145141919810114514191981011451419198101145141919810")
42 | (gdb) print s4
43 | $4 = FastStr::ArcString("1145141919810114514191981011451419198101145141919810")
44 | (gdb) print s5
45 | $5 = FastStr::StaticStr("1145141919810114514191981011451419198101145141919810")
46 | (gdb) print s6
47 | $6 = FastStr::Inline("Hello, World")
48 | ```
49 |
50 | ### LLDB
51 |
52 | ```
53 | $ cargo build -p debugger-example
54 | Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.10s
55 |
56 | $ lldb ../target/debug/debugger-example
57 | (lldb) target create "../target/debug/debugger-example"
58 | Current executable set to '../target/debug/debugger-example' (x86_64).
59 | (lldb) breakpoint set --file main.rs --line 14
60 | Breakpoint 1: 2 locations.
61 | (lldb) run
62 | Process 114514 launched: '../target/debug/debugger-example' (x86_64)
63 | Process 114514 stopped
64 | * thread #1, name = 'debugger-exampl', stop reason = breakpoint 1.1
65 | frame #0: 0x000055555556110d debugger-example`debugger_example::main at main.rs:14:5
66 | 11 let s5 = FastStr::from_static_str(LONG_STRING);
67 | 12 let s6 = FastStr::from_string(SHORT_STRING.to_string());
68 | 13
69 | -> 14 println!("{s1:?}");
70 | 15 println!("{s2:?}");
71 | 16 println!("{s3:?}");
72 | 17 println!("{s4:?}");
73 | (lldb) print s1
74 | (faststr::FastStr) FastStr::Empty("")
75 | (lldb) print s2
76 | (faststr::FastStr) FastStr::Bytes("1145141919810114514191981011451419198101145141919810")
77 | (lldb) print s3
78 | (faststr::FastStr) FastStr::ArcStr("1145141919810114514191981011451419198101145141919810")
79 | (lldb) print s4
80 | (faststr::FastStr) FastStr::ArcString("1145141919810114514191981011451419198101145141919810")
81 | (lldb) print s5
82 | (faststr::FastStr) FastStr::StaticStr("1145141919810114514191981011451419198101145141919810")
83 | (lldb) print s6
84 | (faststr::FastStr) FastStr::Inline("Hello, World")
85 | ```
86 |
--------------------------------------------------------------------------------
/src/serde.rs:
--------------------------------------------------------------------------------
1 | use alloc::{string::String, vec::Vec};
2 | use core::fmt;
3 |
4 | #[cfg(not(feature = "serde-unsafe"))]
5 | use serde::de::Unexpected;
6 | use serde::de::{Deserializer, Error, Visitor};
7 |
8 | use crate::FastStr;
9 |
10 | // https://github.com/serde-rs/serde/blob/629802f2abfd1a54a6072992888fea7ca5bc209f/serde/src/private/de.rs#L56-L125
11 | fn fast_str<'de: 'a, 'a, D>(deserializer: D) -> Result
12 | where
13 | D: Deserializer<'de>,
14 | {
15 | struct FastStrVisitor;
16 |
17 | impl<'a> Visitor<'a> for FastStrVisitor {
18 | type Value = FastStr;
19 |
20 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
21 | formatter.write_str("a string")
22 | }
23 |
24 | fn visit_str(self, v: &str) -> Result
25 | where
26 | E: Error,
27 | {
28 | Ok(FastStr::new(v))
29 | }
30 |
31 | fn visit_borrowed_str(self, v: &'a str) -> Result
32 | where
33 | E: Error,
34 | {
35 | Ok(FastStr::new(v))
36 | }
37 |
38 | fn visit_string(self, v: String) -> Result
39 | where
40 | E: Error,
41 | {
42 | Ok(FastStr::from(v))
43 | }
44 |
45 | fn visit_bytes(self, v: &[u8]) -> Result
46 | where
47 | E: Error,
48 | {
49 | #[cfg(feature = "serde-unsafe")]
50 | {
51 | Ok(unsafe { FastStr::new_u8_slice_unchecked(v) })
52 | }
53 | #[cfg(not(feature = "serde-unsafe"))]
54 | match FastStr::new_u8_slice(v) {
55 | Ok(s) => Ok(s),
56 | Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
57 | }
58 | }
59 |
60 | fn visit_borrowed_bytes(self, v: &'a [u8]) -> Result
61 | where
62 | E: Error,
63 | {
64 | #[cfg(feature = "serde-unsafe")]
65 | {
66 | Ok(unsafe { FastStr::new_u8_slice_unchecked(v) })
67 | }
68 | #[cfg(not(feature = "serde-unsafe"))]
69 | match FastStr::new_u8_slice(v) {
70 | Ok(s) => Ok(s),
71 | Err(_) => Err(Error::invalid_value(Unexpected::Bytes(v), &self)),
72 | }
73 | }
74 |
75 | fn visit_byte_buf(self, v: Vec) -> Result
76 | where
77 | E: Error,
78 | {
79 | #[cfg(not(feature = "serde-unsafe"))]
80 | simdutf8::basic::from_utf8(&v)
81 | .map_err(|_| Error::invalid_value(Unexpected::Bytes(&v), &self))?;
82 | // Safety: we have checked that v is valid utf-8
83 | Ok(unsafe { FastStr::from_vec_u8_unchecked(v) })
84 | }
85 | }
86 |
87 | deserializer.deserialize_string(FastStrVisitor)
88 | }
89 |
90 | impl serde::Serialize for FastStr {
91 | fn serialize(&self, serializer: S) -> Result
92 | where
93 | S: serde::Serializer,
94 | {
95 | self.as_str().serialize(serializer)
96 | }
97 | }
98 |
99 | impl<'de> serde::Deserialize<'de> for FastStr {
100 | fn deserialize(deserializer: D) -> Result
101 | where
102 | D: serde::Deserializer<'de>,
103 | {
104 | fast_str(deserializer)
105 | }
106 | }
107 |
--------------------------------------------------------------------------------
/utils/faststr_gdb.py:
--------------------------------------------------------------------------------
1 | import gdb
2 |
3 | VARIANT_NAMES = ['Empty', 'Bytes', 'ArcStr',
4 | 'ArcString', 'StaticStr', 'Inline']
5 |
6 |
7 | class FastStrPrettyPrinter:
8 | def __init__(self, valobj: gdb.Value):
9 | repr_obj = valobj['__0']
10 | inner = repr_obj[repr_obj.type.fields()[0]]
11 | fields = inner.type.fields()
12 | discr = int(inner[fields[0]]) + 1
13 | field_name = fields[discr].name
14 | assert field_name == VARIANT_NAMES[discr-1]
15 | variant = inner[fields[discr]]
16 |
17 | self._variant_name = field_name
18 | self._display_string = ''
19 | self._is_error = False
20 |
21 | if discr == 1:
22 | pass
23 | elif discr == 2:
24 | self._display_string = self._extract_bytes(variant)
25 | elif discr == 3:
26 | self._display_string = self._extract_arc_str(variant)
27 | elif discr == 4:
28 | self._display_string = self._extract_arc_string(variant)
29 | elif discr == 5:
30 | self._display_string = self._extract_static_str(variant)
31 | elif discr == 6:
32 | self._display_string = self._extract_inline(variant)
33 | else:
34 | self._display_string = ''
35 | self._is_error = True
36 |
37 | def _extract_bytes(self, variant: gdb.Value) -> str:
38 | try:
39 | bytes_obj = variant['__0']
40 | length = int(bytes_obj['len'])
41 | ptr = bytes_obj['ptr']
42 | return ptr.string('utf-8', length=length)
43 | except Exception as e:
44 | self._is_error = True
45 | return f''
46 |
47 | def _extract_arc_str(self, variant: gdb.Value) -> str:
48 | try:
49 | arc_obj = variant['__0']
50 | non_null_ptr = arc_obj['ptr']
51 | arc_inner_ptr = non_null_ptr['pointer']
52 | data_ptr = arc_inner_ptr['data_ptr']
53 | length = int(arc_inner_ptr['length'])
54 | arc_inner = data_ptr.dereference()
55 | str_data = arc_inner['data']
56 | data = gdb.selected_inferior().read_memory(str_data.address, length)
57 | return data.tobytes().decode('utf-8')
58 | except Exception as e:
59 | self._is_error = True
60 | return f''
61 |
62 | def _extract_arc_string(self, variant: gdb.Value) -> str:
63 | try:
64 | arc_obj = variant['__0']
65 | non_null_ptr = arc_obj['ptr']
66 | arc_inner_ptr = non_null_ptr['pointer']
67 | arc_inner = arc_inner_ptr.dereference()
68 | string_obj = arc_inner['data']
69 | vec_obj = string_obj['vec']
70 | length = int(vec_obj['len'])
71 | buf = vec_obj['buf']
72 | raw_vec_inner = buf['inner']
73 | unique_ptr = raw_vec_inner['ptr']
74 | non_null_u8_ptr = unique_ptr['pointer']
75 | ptr = non_null_u8_ptr['pointer']
76 | return ptr.string('utf-8', length=length)
77 | except Exception as e:
78 | self._is_error = True
79 | return f''
80 |
81 | def _extract_static_str(self, variant: gdb.Value) -> str:
82 | try:
83 | str_ref = variant['__0']
84 | length = int(str_ref['length'])
85 | data_ptr = str_ref['data_ptr']
86 | return data_ptr.string('utf-8', length=length)
87 | except Exception as e:
88 | self._is_error = True
89 | return f''
90 |
91 | def _extract_inline(self, variant: gdb.Value) -> str:
92 | try:
93 | length = int(variant['len'])
94 | buf = variant['buf']
95 | data = bytes([int(buf[i]) for i in range(length)])
96 | return data.decode('utf-8')
97 | except Exception as e:
98 | self._is_error = True
99 | return f''
100 |
101 | def to_string(self) -> str:
102 | return self._display_string if self._is_error else f'FastStr::{self._variant_name}("{self._display_string}")'
103 |
104 |
105 | def faststr_pretty_printer(valobj: gdb.Value):
106 | type_name = str(valobj.type.strip_typedefs())
107 | if type_name == 'faststr::FastStr':
108 | return FastStrPrettyPrinter(valobj)
109 | return None
110 |
111 |
112 | gdb.pretty_printers.append(faststr_pretty_printer)
113 |
--------------------------------------------------------------------------------
/CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | # Contributor Covenant Code of Conduct
2 |
3 | Since this is a Rust project, we also adheres to the [Rust Code Of Conduct][rustcoc].
4 | This describes the minimum behavior expected from all contributors.
5 |
6 | [rustcoc]: https://www.rust-lang.org/policies/code-of-conduct
7 |
8 | ## Our Pledge
9 |
10 | We as members, contributors, and leaders pledge to make participation in our
11 | community a harassment-free experience for everyone, regardless of age, body
12 | size, visible or invisible disability, ethnicity, sex characteristics, gender
13 | identity and expression, level of experience, education, socio-economic status,
14 | nationality, personal appearance, race, religion, or sexual identity
15 | and orientation.
16 |
17 | We pledge to act and interact in ways that contribute to an open, welcoming,
18 | diverse, inclusive, and healthy community.
19 |
20 | ## Our Standards
21 |
22 | Examples of behavior that contributes to a positive environment for our
23 | community include:
24 |
25 | - Demonstrating empathy and kindness toward other people
26 | - Being respectful of differing opinions, viewpoints, and experiences
27 | - Giving and gracefully accepting constructive feedback
28 | - Accepting responsibility and apologizing to those affected by our mistakes,
29 | and learning from the experience
30 | - Focusing on what is best not just for us as individuals, but for the
31 | overall community
32 |
33 | Examples of unacceptable behavior include:
34 |
35 | - The use of sexualized language or imagery, and sexual attention or
36 | advances of any kind
37 | - Trolling, insulting or derogatory comments, and personal or political attacks
38 | - Public or private harassment
39 | - Publishing others' private information, such as a physical or email
40 | address, without their explicit permission
41 | - Other conduct which could reasonably be considered inappropriate in a
42 | professional setting
43 |
44 | ## Enforcement Responsibilities
45 |
46 | Community leaders are responsible for clarifying and enforcing our standards of
47 | acceptable behavior and will take appropriate and fair corrective action in
48 | response to any behavior that they deem inappropriate, threatening, offensive,
49 | or harmful.
50 |
51 | Community leaders have the right and responsibility to remove, edit, or reject
52 | comments, commits, code, wiki edits, issues, and other contributions that are
53 | not aligned to this Code of Conduct, and will communicate reasons for moderation
54 | decisions when appropriate.
55 |
56 | ## Scope
57 |
58 | This Code of Conduct applies within all community spaces, and also applies when
59 | an individual is officially representing the community in public spaces.
60 | Examples of representing our community include using an official e-mail address,
61 | posting via an official social media account, or acting as an appointed
62 | representative at an online or offline event.
63 |
64 | ## Enforcement
65 |
66 | Instances of abusive, harassing, or otherwise unacceptable behavior may be
67 | reported to the community leaders responsible for enforcement at
68 | [conduct@cloudwego.io](mailto:conduct@cloudwego.io).
69 | All complaints will be reviewed and investigated promptly and fairly.
70 |
71 | All community leaders are obligated to respect the privacy and security of the
72 | reporter of any incident.
73 |
74 | ## Enforcement Guidelines
75 |
76 | Community leaders will follow these Community Impact Guidelines in determining
77 | the consequences for any action they deem in violation of this Code of Conduct:
78 |
79 | ### 1. Correction
80 |
81 | **Community Impact**: Use of inappropriate language or other behavior deemed
82 | unprofessional or unwelcome in the community.
83 |
84 | **Consequence**: A private, written warning from community leaders, providing
85 | clarity around the nature of the violation and an explanation of why the
86 | behavior was inappropriate. A public apology may be requested.
87 |
88 | ### 2. Warning
89 |
90 | **Community Impact**: A violation through a single incident or series
91 | of actions.
92 |
93 | **Consequence**: A warning with consequences for continued behavior. No
94 | interaction with the people involved, including unsolicited interaction with
95 | those enforcing the Code of Conduct, for a specified period of time. This
96 | includes avoiding interactions in community spaces as well as external channels
97 | like social media. Violating these terms may lead to a temporary or
98 | permanent ban.
99 |
100 | ### 3. Temporary Ban
101 |
102 | **Community Impact**: A serious violation of community standards, including
103 | sustained inappropriate behavior.
104 |
105 | **Consequence**: A temporary ban from any sort of interaction or public
106 | communication with the community for a specified period of time. No public or
107 | private interaction with the people involved, including unsolicited interaction
108 | with those enforcing the Code of Conduct, is allowed during this period.
109 | Violating these terms may lead to a permanent ban.
110 |
111 | ### 4. Permanent Ban
112 |
113 | **Community Impact**: Demonstrating a pattern of violation of community
114 | standards, including sustained inappropriate behavior, harassment of an
115 | individual, or aggression toward or disparagement of classes of individuals.
116 |
117 | **Consequence**: A permanent ban from any sort of public interaction within
118 | the community.
119 |
120 | ## Attribution
121 |
122 | This Code of Conduct is adapted from the [Contributor Covenant][homepage],
123 | version 2.0, available at
124 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
125 |
126 | Community Impact Guidelines were inspired by [Mozilla's code of conduct
127 | enforcement ladder](https://github.com/mozilla/diversity).
128 |
129 | [homepage]: https://www.contributor-covenant.org
130 |
131 | For answers to common questions about this code of conduct, see the FAQ at
132 | https://www.contributor-covenant.org/faq. Translations are available at
133 | https://www.contributor-covenant.org/translations.
134 |
--------------------------------------------------------------------------------
/utils/faststr_lldb.py:
--------------------------------------------------------------------------------
1 | import lldb
2 | import re
3 |
4 | VARIANT_NAMES = ['Empty', 'Bytes', 'ArcStr',
5 | 'ArcString', 'StaticStr', 'Inline']
6 |
7 |
8 | class FastStrSyntheticProvider:
9 | def __init__(self, valobj: lldb.SBValue, _internal_dict: dict):
10 | # IMPORTANT: use non-synthetic value instead of formatted value by Rust official lldb plugin
11 | self.valobj = valobj.GetNonSyntheticValue()
12 | self.update()
13 |
14 | def update(self):
15 | repr = self.valobj.GetChildAtIndex(0)
16 | variants = repr.GetChildMemberWithName('$variants$')
17 | discr = variants.GetChildAtIndex(0).GetChildMemberWithName(
18 | '$discr$').GetValueAsUnsigned()
19 | variant = variants.GetChildAtIndex(discr)
20 | variant_name = self._get_variant_name(variant)
21 | assert variant_name == VARIANT_NAMES[discr]
22 |
23 | self._variant_name = variant_name
24 | self._display_string = ''
25 | self._is_error = False
26 |
27 | if variant_name == 'Empty':
28 | self._display_string = ''
29 | elif variant_name == 'Bytes':
30 | self._display_string = self._extract_bytes(variant)
31 | elif variant_name == 'ArcStr':
32 | self._display_string = self._extract_arc_str(variant)
33 | elif variant_name == 'ArcString':
34 | self._display_string = self._extract_arc_string(variant)
35 | elif variant_name == 'StaticStr':
36 | self._display_string = self._extract_static_str(variant)
37 | elif variant_name == 'Inline':
38 | self._display_string = self._extract_inline(variant)
39 | else:
40 | self._display_string = ''
41 | self._is_error = True
42 |
43 | def _get_variant_name(self, variant: lldb.SBValue):
44 | full_name = variant.GetType().GetName()
45 | # faststr::Repr::faststr::Repr$Inner::Empty$Variant
46 | return re.match('^([a-zA-Z:]+)\\$Inner::([a-zA-Z]+)\\$Variant$', full_name).group(2)
47 |
48 | def _extract_bytes(self, variant: lldb.SBValue) -> str:
49 | bytes_obj = variant.GetChildMemberWithName(
50 | 'value').GetChildMemberWithName('__0')
51 | ptr = bytes_obj.GetChildMemberWithName('ptr').GetValueAsUnsigned()
52 | length = bytes_obj.GetChildMemberWithName('len').GetValueAsUnsigned()
53 | error = lldb.SBError()
54 | data = variant.GetProcess().ReadMemory(ptr, length, error)
55 | if error.Success():
56 | return data.decode('utf-8')
57 | else:
58 | self._is_error = True
59 | return f''
60 |
61 | def _extract_arc_str(self, variant: lldb.SBValue) -> str:
62 | # Arc
63 | arc_str = variant.GetChildMemberWithName(
64 | 'value').GetChildMemberWithName('__0')
65 | ptr = arc_str.GetChildMemberWithName('ptr')
66 | # ArcInner
67 | pointer = ptr.GetChildMemberWithName('pointer')
68 | # str
69 | data_ptr = pointer.GetChildMemberWithName('data_ptr')
70 | length = pointer.GetChildMemberWithName('length').GetValueAsUnsigned()
71 | data = data_ptr.GetChildMemberWithName('data')
72 | error = lldb.SBError()
73 | data = variant.GetProcess().ReadMemory(
74 | data.AddressOf().GetValueAsUnsigned(), length, error)
75 | if error.Success():
76 | return data.decode('utf-8')
77 | else:
78 | self._is_error = True
79 | return f''
80 |
81 | def _extract_arc_string(self, variant: lldb.SBValue) -> str:
82 | # Arc
83 | arc_str = variant.GetChildMemberWithName(
84 | 'value').GetChildMemberWithName('__0')
85 | ptr = arc_str.GetChildMemberWithName('ptr')
86 | # ArcInner
87 | arc_inner = ptr.GetChildMemberWithName('pointer')
88 | # String
89 | data = arc_inner.GetChildMemberWithName('data')
90 | # inner Vec
91 | vec = data.GetChildMemberWithName('vec')
92 | pointer = vec.GetChildMemberWithName('buf').GetChildMemberWithName('inner').GetChildMemberWithName(
93 | 'ptr').GetChildMemberWithName('pointer').GetChildMemberWithName('pointer')
94 | length = vec.GetChildMemberWithName('len').GetValueAsUnsigned()
95 | error = lldb.SBError()
96 | data = variant.GetProcess().ReadMemory(
97 | pointer.GetValueAsUnsigned(), length, error)
98 | if error.Success():
99 | return data.decode('utf-8')
100 | else:
101 | self._is_error = True
102 | return f''
103 |
104 | def _extract_static_str(self, variant: lldb.SBValue) -> str:
105 | # &'static str
106 | static_str = variant.GetChildMemberWithName(
107 | 'value').GetChildMemberWithName('__0')
108 | data_ptr = static_str.GetChildMemberWithName('data_ptr')
109 | length = static_str.GetChildMemberWithName(
110 | 'length').GetValueAsUnsigned()
111 | error = lldb.SBError()
112 | data = variant.GetProcess().ReadMemory(
113 | data_ptr.GetValueAsUnsigned(), length, error)
114 | if error.Success():
115 | return data.decode('utf-8')
116 | else:
117 | self._is_error = True
118 | return f''
119 |
120 | def _extract_inline(self, variant: lldb.SBValue) -> str:
121 | # inline
122 | inline = variant.GetChildMemberWithName('value')
123 | buf = inline.GetChildMemberWithName('buf')
124 | length = inline.GetChildMemberWithName('len').GetValueAsUnsigned()
125 | error = lldb.SBError()
126 | data = variant.GetProcess().ReadMemory(
127 | buf.AddressOf().GetValueAsUnsigned(), length, error)
128 | if error.Success():
129 | return data.decode('utf-8')
130 | else:
131 | self._is_error = True
132 | return f''
133 |
134 | def to_string(self) -> str:
135 | return self._display_string if self._is_error else f'FastStr::{self._variant_name}("{self._display_string}")'
136 |
137 |
138 | def FastStrSummaryProvider(valobj: lldb.SBValue, internal_dict: dict) -> str:
139 | return FastStrSyntheticProvider(valobj, internal_dict).to_string()
140 |
141 |
142 | def __lldb_init_module(debugger, internal_dict):
143 | debugger.HandleCommand(
144 | 'type synthetic add -F faststr_lldb.VSCodeFastStrSyntheticProvider faststr::FastStr'
145 | )
146 | debugger.HandleCommand(
147 | 'type summary add -F faststr_lldb.FastStrSummaryProvider faststr::FastStr'
148 | )
149 |
--------------------------------------------------------------------------------
/src/sea_orm.rs:
--------------------------------------------------------------------------------
1 | use sea_orm::prelude::StringLen;
2 |
3 | use crate::FastStr;
4 |
5 | impl std::convert::From for sea_orm::Value {
6 | fn from(source: FastStr) -> Self {
7 | sea_orm::Value::String(Some(Box::new(source.into())))
8 | }
9 | }
10 |
11 | impl sea_orm::TryFromU64 for FastStr {
12 | fn try_from_u64(value: u64) -> Result {
13 | Ok(FastStr::new(itoa::Buffer::new().format(value)))
14 | }
15 | }
16 |
17 | impl sea_orm::TryGetable for FastStr {
18 | fn try_get_by(
19 | res: &sea_orm::QueryResult,
20 | idx: I,
21 | ) -> Result {
22 | let val: String = String::try_get_by(res, idx)?;
23 | Ok(FastStr::from_string(val))
24 | }
25 | }
26 |
27 | impl sea_orm::sea_query::Nullable for FastStr {
28 | fn null() -> sea_orm::Value {
29 | sea_orm::Value::String(None)
30 | }
31 | }
32 |
33 | impl sea_orm::sea_query::ValueType for FastStr {
34 | fn try_from(v: sea_orm::Value) -> Result {
35 | match v {
36 | sea_orm::Value::String(Some(x)) => Ok(FastStr::from_string(*x)),
37 | _ => Err(sea_orm::sea_query::ValueTypeErr),
38 | }
39 | }
40 |
41 | fn type_name() -> String {
42 | stringify!(FastStr).to_owned()
43 | }
44 |
45 | fn array_type() -> sea_orm::sea_query::ArrayType {
46 | sea_orm::sea_query::ArrayType::String
47 | }
48 |
49 | fn column_type() -> sea_orm::sea_query::ColumnType {
50 | sea_orm::sea_query::ColumnType::String(StringLen::None)
51 | }
52 | }
53 |
54 | #[cfg(test)]
55 | mod tests {
56 | use sea_orm::{
57 | entity::prelude::*, ActiveValue::Set, DerivePrimaryKey, MockDatabase, QueryTrait,
58 | TryFromU64 as _,
59 | };
60 |
61 | use super::*;
62 |
63 | mod test_book {
64 | use super::*;
65 |
66 | #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
67 | #[sea_orm(table_name = "test_book")]
68 | pub struct Model {
69 | #[sea_orm(primary_key)]
70 | pub id: FastStr,
71 | }
72 | #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
73 | pub enum Relation {
74 | #[sea_orm(has_many = "super::test_page::Entity")]
75 | TestPage,
76 | }
77 |
78 | impl Related for Entity {
79 | fn to() -> sea_orm::RelationDef {
80 | Relation::TestPage.def()
81 | }
82 | }
83 |
84 | impl ActiveModelBehavior for ActiveModel {}
85 | }
86 |
87 | mod test_page {
88 | use super::*;
89 |
90 | #[derive(Clone, Debug, PartialEq, DeriveEntityModel, Eq)]
91 | #[sea_orm(table_name = "test_page")]
92 | pub struct Model {
93 | #[sea_orm(primary_key)]
94 | pub id: FastStr,
95 | pub book_id: FastStr,
96 | }
97 |
98 | #[derive(Copy, Clone, Debug, EnumIter, DeriveRelation)]
99 | pub enum Relation {
100 | #[sea_orm(
101 | belongs_to = "super::test_book::Entity",
102 | from = "Column::BookId",
103 | to = "super::test_book::Column::Id"
104 | )]
105 | TestBook,
106 | }
107 |
108 | impl Related for Entity {
109 | fn to() -> sea_orm::RelationDef {
110 | Relation::TestBook.def()
111 | }
112 | }
113 |
114 | impl ActiveModelBehavior for ActiveModel {}
115 | }
116 |
117 | #[test]
118 | fn test_value_conversion() {
119 | let test_str = FastStr::from_static_str("test string");
120 |
121 | // Test From for Value
122 | let value: sea_orm::Value = test_str.clone().into();
123 | assert!(matches!(value, sea_orm::Value::String(Some(_))));
124 |
125 | // Test null value
126 | let null_value = ::null();
127 | assert!(matches!(null_value, sea_orm::Value::String(None)));
128 | }
129 |
130 | #[test]
131 | fn test_query() {
132 | let test_str = FastStr::from_static_str("test string");
133 |
134 | let db = sea_orm::DatabaseBackend::MySql;
135 | let select_query = test_book::Entity::find()
136 | .filter(test_book::Column::Id.eq(test_str.clone()))
137 | .build(db);
138 | assert_eq!(
139 | select_query.to_string(),
140 | "SELECT `test_book`.`id` FROM `test_book` WHERE `test_book`.`id` = 'test string'"
141 | );
142 |
143 | let mutate_query = test_book::Entity::insert(test_book::ActiveModel {
144 | id: Set(test_str.clone()),
145 | })
146 | .build(db);
147 | assert_eq!(
148 | mutate_query.to_string(),
149 | "INSERT INTO `test_book` (`id`) VALUES ('test string')"
150 | );
151 |
152 | let remove_query = test_book::Entity::delete(test_book::ActiveModel {
153 | id: Set(test_str.clone()),
154 | })
155 | .build(db);
156 | assert_eq!(
157 | remove_query.to_string(),
158 | "DELETE FROM `test_book` WHERE `test_book`.`id` = 'test string'"
159 | );
160 | }
161 |
162 | #[test]
163 | fn test_relation() {
164 | // left join
165 | let test_str = FastStr::from_static_str("test string");
166 | let db = sea_orm::DatabaseBackend::MySql;
167 | let select_query = test_book::Entity::find()
168 | .inner_join(test_page::Entity)
169 | .filter(test_book::Column::Id.eq(test_str))
170 | .build(db);
171 | assert_eq!(
172 | select_query.to_string(),
173 | "SELECT `test_book`.`id` FROM `test_book` INNER JOIN `test_page` ON `test_book`.`id` \
174 | = `test_page`.`book_id` WHERE `test_book`.`id` = 'test string'"
175 | );
176 | }
177 |
178 | #[tokio::test]
179 | async fn test_query_result() {
180 | let test_str = FastStr::from_static_str("test string");
181 | let db = MockDatabase::new(sea_orm::DatabaseBackend::MySql)
182 | .append_query_results([vec![test_book::Model {
183 | id: test_str.clone(),
184 | }]])
185 | .into_connection();
186 |
187 | let result = test_book::Entity::find()
188 | .filter(test_book::Column::Id.eq(test_str.clone()))
189 | .one(&db)
190 | .await
191 | .unwrap();
192 | assert_eq!(result, Some(test_book::Model { id: test_str }));
193 | }
194 |
195 | #[tokio::test]
196 | async fn test_try_from_u64() {
197 | assert_eq!(
198 | FastStr::try_from_u64(1234567890),
199 | Ok(FastStr::from_static_str("1234567890"))
200 | );
201 | }
202 | }
203 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # faststr
2 |
3 | [](https://crates.io/crates/faststr)
4 | [](https://docs.rs/faststr)
5 | [](https://deepwiki.com/volo-rs/faststr)
6 | [](https://www.cloudwego.io/)
7 | [](#license)
8 | [![Build Status][actions-badge]][actions-url]
9 |
10 | [actions-badge]: https://github.com/volo-rs/faststr/actions/workflows/ci.yaml/badge.svg
11 | [actions-url]: https://github.com/volo-rs/faststr/actions
12 |
13 | `faststr` is a string library that try to avoid the cost of clone.
14 |
15 | ## Why we need it?
16 |
17 | In Rust, the String type is commonly used, but it has the following problems:
18 |
19 | 1. In many scenarios in asynchronous Rust, we cannot determine when a String is dropped. For example, when we send a String through RPC/HTTP, we cannot explicitly mark the lifetime, thus we must clone it;
20 | 2. Rust's asynchronous ecosystem is mainly based on Tokio, with network programming largely relying on bytes::Bytes. We can take advantage of Bytes to avoid cloning Strings, while better integrating with the Bytes ecosystem;
21 | 3. Even in purely synchronous code, when the code is complex enough, marking the lifetime can greatly affect code readability and maintainability. In business development experience, there will often be multiple Strings from different sources combined into a single Struct for processing. In such situations, it's almost impossible to avoid cloning using lifetimes;
22 | 4. Cloning a String is quite costly;
23 |
24 | Therefore, we have created the `FastStr` type. By sacrificing immutability, we can avoid the overhead of cloning Strings and better integrate with Rust's asynchronous, microservice, and network programming ecosystems.
25 |
26 | ## When should I use it?
27 |
28 | 1. When you need to send a String through RPC/HTTP;
29 | 2. When you read a String from a file or database or config;
30 | 3. Everywhere when you don't need to mutate the String anymore;
31 |
32 | ## How to migrate to `FastStr`?
33 |
34 | `FastStr` implements `From` trait for various types, so you can easily migrate to `FastStr` by replacing `String` with `FastStr` and adding `.into()`.
35 |
36 | **Note:** The memory size of `FastStr` is not `24`, so switching from `String` or [`SmolStr`](https://docs.rs/smol_str/latest/smol_str/struct.SmolStr.html) to `FastStr` may not be harmless.
37 |
38 | For example, if your API is something like this:
39 |
40 | ```rust
41 | fn need_a_string(s: String)
42 | ```
43 |
44 | You may change it to:
45 |
46 | ```rust
47 | fn need_a_string>(s: S)
48 | ```
49 |
50 | This will not be a break change for users.
51 |
52 | ## Features
53 |
54 | - `serde`: Enable serde support.
55 | - `serde-unsafe`: Enable serde support with utf8 validation disabled.
56 | - `redis`: Enable redis support.
57 | - `redis-unsafe`: Enable redis support with utf8 validation disabled.
58 |
59 | ## Benchmark
60 |
61 | ```bash
62 | $ cargo bench
63 | ```
64 |
65 | ### AARCH64
66 |
67 | #### M3Max
68 |
69 | ```
70 | empty faststr time: [2.0188 ns 2.0271 ns 2.0356 ns]
71 |
72 | empty string time: [2.1306 ns 2.1333 ns 2.1365 ns]
73 |
74 | static faststr time: [2.0458 ns 2.0589 ns 2.0709 ns]
75 |
76 | inline faststr time: [2.2270 ns 2.2332 ns 2.2399 ns]
77 |
78 | string hello world time: [12.553 ns 12.575 ns 12.597 ns]
79 |
80 | 512B faststr time: [3.8373 ns 3.8454 ns 3.8540 ns]
81 |
82 | 512B string time: [36.895 ns 37.007 ns 37.121 ns]
83 |
84 | 4096B faststr time: [3.8205 ns 3.8260 ns 3.8317 ns]
85 |
86 | 4096B string time: [55.275 ns 55.355 ns 55.446 ns]
87 |
88 | 16384B faststr time: [3.8191 ns 3.8246 ns 3.8306 ns]
89 |
90 | 16384B string time: [338.18 ns 352.36 ns 365.02 ns]
91 |
92 | 65536B faststr time: [3.8169 ns 3.8221 ns 3.8277 ns]
93 |
94 | 65536B string time: [662.52 ns 663.75 ns 664.96 ns]
95 |
96 | 524288B faststr time: [3.8140 ns 3.8178 ns 3.8219 ns]
97 |
98 | 524288B string time: [6.2681 µs 6.2755 µs 6.2827 µs]
99 |
100 | 1048576B faststr time: [3.8235 ns 3.8290 ns 3.8348 ns]
101 |
102 | 1048576B string time: [12.422 µs 12.438 µs 12.453 µs]
103 | ```
104 |
105 | ### amd64
106 |
107 | #### AMD EPYC 7Y83
108 |
109 | ```
110 | empty faststr time: [4.3325 ns 4.3330 ns 4.3335 ns]
111 |
112 | empty string time: [4.6413 ns 4.6422 ns 4.6434 ns]
113 |
114 | static faststr time: [4.3328 ns 4.3333 ns 4.3339 ns]
115 |
116 | inline faststr time: [4.6567 ns 4.6580 ns 4.6593 ns]
117 |
118 | string hello world time: [12.897 ns 12.929 ns 12.954 ns]
119 |
120 | 512B faststr time: [4.4218 ns 4.4253 ns 4.4291 ns]
121 |
122 | 512B string time: [16.087 ns 16.094 ns 16.105 ns]
123 |
124 | 4096B faststr time: [4.4066 ns 4.4099 ns 4.4141 ns]
125 |
126 | 4096B string time: [96.905 ns 97.401 ns 97.879 ns]
127 |
128 | 16384B faststr time: [4.4150 ns 4.4277 ns 4.4414 ns]
129 |
130 | 16384B string time: [229.25 ns 229.30 ns 229.34 ns]
131 |
132 | 65536B faststr time: [4.4562 ns 4.4623 ns 4.4690 ns]
133 |
134 | 65536B string time: [1.3325 µs 1.3328 µs 1.3332 µs]
135 |
136 | 524288B faststr time: [4.4167 ns 4.4240 ns 4.4326 ns]
137 |
138 | 524288B string time: [18.268 µs 18.277 µs 18.287 µs]
139 |
140 | 1048576B faststr time: [4.4275 ns 4.4385 ns 4.4494 ns]
141 |
142 | 1048576B string time: [32.839 µs 33.777 µs 34.554 µs]
143 | ```
144 |
145 | ## Related Projects
146 |
147 | - [Volo][Volo]: Rust RPC framework with high-performance and strong-extensibility for building micro-services.
148 | - [Motore][Motore]: Middleware abstraction layer powered by GAT.
149 | - [Pilota][Pilota]: A thrift and protobuf implementation in pure rust with high performance and extensibility.
150 | - [Metainfo][Metainfo]: Transmissing metainfo across components.
151 |
152 | ## Contributing
153 |
154 | See [CONTRIBUTING.md](https://github.com/volo-rs/faststr/blob/main/CONTRIBUTING.md) for more information.
155 |
156 | All contributions are welcomed!
157 |
158 | ## License
159 |
160 | `faststr` is dual-licensed under the MIT license and the Apache License (Version 2.0).
161 |
162 | See [LICENSE-MIT](https://github.com/volo-rs/faststr/blob/main/LICENSE-MIT) and [LICENSE-APACHE](https://github.com/volo-rs/faststr/blob/main/LICENSE-APACHE) for details.
163 |
164 | ## Credits
165 |
166 | `faststr` copied and used some code from [`smol_str`](https://github.com/rust-analyzer/smol_str), which is also licensed under the MIT license and the Apache License (Version 2.0).
167 |
168 | We really appreciate the work of `smol_str` team.
169 |
170 | ## Community
171 |
172 | - Email: [volo@cloudwego.io](mailto:volo@cloudwego.io)
173 | - How to become a member: [COMMUNITY MEMBERSHIP](https://github.com/cloudwego/community/blob/main/COMMUNITY_MEMBERSHIP.md)
174 | - Issues: [Issues](https://github.com/volo-rs/faststr/issues)
175 | - Feishu: Scan the QR code below with [Feishu](https://www.feishu.cn/) or [click this link](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=b34v5470-8e4d-4c7d-bf50-8b2917af026b) to join our CloudWeGo Volo user group.
176 |
177 |
178 |
179 | [Volo]: https://github.com/cloudwego/volo
180 | [Motore]: https://github.com/cloudwego/motore
181 | [Pilota]: https://github.com/cloudwego/pilota
182 | [Metainfo]: https://github.com/cloudwego/metainfo
183 |
--------------------------------------------------------------------------------
/LICENSE-APACHE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to faststr
2 |
3 | :balloon: Thanks for your help improving the project! We are so happy to have you!
4 |
5 | There are opportunities to contribute to faststr at any level. It doesn't matter if
6 | you are just getting started with Rust or are the most weathered expert, we can
7 | use your help.
8 |
9 | **No contribution is too small and all contributions are valued.**
10 |
11 | This guide will help you get started. **Do not let this guide intimidate you**.
12 | It should be considered a map to help you navigate the process.
13 |
14 | The develop discussion group on Feishu is available for any concerns not covered in this
15 | guide, please join us!
16 |
17 |
18 |
19 | _This guide is adapted from the [Tokio contributing guide](https://github.com/tokio-rs/tokio/blob/master/CONTRIBUTING.md)_.
20 |
21 | ## Conduct
22 |
23 | See the [faststr Code of Conduct](https://github.com/volo-rs/faststr/blob/main/CODE_OF_CONDUCT.md).
24 |
25 | ## Contributing in Issues
26 |
27 | For any issue, there are fundamentally three ways an individual can contribute:
28 |
29 | 1. By opening the issue for discussion: For instance, if you believe that you
30 | have discovered a bug in faststr, creating a new issue in [the volo-rs/faststr
31 | issue tracker][issue] is the way to report it.
32 |
33 | 2. By helping to triage the issue: This can be done by providing
34 | supporting details (a test case that demonstrates a bug), providing
35 | suggestions on how to address the issue, or ensuring that the issue is tagged
36 | correctly.
37 |
38 | 3. By helping to resolve the issue: Typically this is done either in the form of
39 | demonstrating that the issue reported is not a problem after all, or more
40 | often, by opening a Pull Request that changes some bit of something in
41 | faststr in a concrete and reviewable manner.
42 |
43 | [issue]: https://github.com/volo-rs/faststr/issues
44 |
45 | **Anybody can participate in any stage of contribution**. We urge you to
46 | participate in the discussion around bugs and participate in reviewing PRs.
47 |
48 | ### Asking for General Help
49 |
50 | If you have reviewed existing documentation and still have questions or are
51 | having problems, you can either:
52 |
53 | 1. Submit a new issue and describes your problem, or
54 | 2. Join the [Volo user group on Feishu](https://applink.feishu.cn/client/chat/chatter/add_by_link?link_token=b34v5470-8e4d-4c7d-bf50-8b2917af026b) and ask for help there.
55 |
56 | In exchange for receiving help, we expect you to contribute back a documentation
57 | PR that helps others avoid the problems that you encountered.
58 |
59 | ### Submitting a Bug Report
60 |
61 | When opening a new issue in the faststr issue tracker, you will be presented
62 | with a basic template that should be filled in. If you believe that you have
63 | uncovered a bug, please fill out this form, following the template to the best
64 | of your ability. Do not worry if you cannot answer every detail, just fill in
65 | what you can.
66 |
67 | The two most important pieces of information we need in order to properly
68 | evaluate the report is a description of the behavior you are seeing and a simple
69 | test case we can use to recreate the problem on our own. If we cannot recreate
70 | the issue, it becomes impossible for us to fix.
71 |
72 | In order to rule out the possibility of bugs introduced by userland code, test
73 | cases should be limited, as much as possible, to using only faststr APIs.
74 |
75 | See [How to create a Minimal, Complete, and Verifiable example][mcve].
76 |
77 | [mcve]: https://stackoverflow.com/help/mcve
78 |
79 | ### Triaging a Bug Report
80 |
81 | Once an issue has been opened, it is not uncommon for there to be discussion
82 | around it. Some contributors may have differing opinions about the issue,
83 | including whether the behavior being seen is a bug or a feature. This discussion
84 | is part of the process and should be kept focused, helpful, and professional.
85 |
86 | Short, clipped responses—that provide neither additional context nor supporting
87 | detail—are not helpful or professional. To many, such responses are simply
88 | annoying and unfriendly.
89 |
90 | Contributors are encouraged to help one another make forward progress as much as
91 | possible, empowering one another to solve issues collaboratively. If you choose
92 | to comment on an issue that you feel either is not a problem that needs to be
93 | fixed, or if you encounter information in an issue that you feel is incorrect,
94 | explain why you feel that way with additional supporting context, and be willing
95 | to be convinced that you may be wrong. By doing so, we can often reach the
96 | correct outcome much faster.
97 |
98 | ### Resolving a Bug Report
99 |
100 | In the majority of cases, issues are resolved by opening a Pull Request. The
101 | process for opening and reviewing a Pull Request is similar to that of opening
102 | and triaging issues, but carries with it a necessary review and approval
103 | workflow that ensures that the proposed changes meet the minimal quality and
104 | functional guidelines of the faststr project.
105 |
106 | ## Pull Requests
107 |
108 | Pull Requests are the way concrete changes are made to the code, documentation,
109 | and dependencies in the faststr repository.
110 |
111 | Even tiny pull requests (e.g., one character pull request fixing a typo in API
112 | documentation) are greatly appreciated. Before making a large change, it is
113 | usually a good idea to first open an issue describing the change to solicit
114 | feedback and guidance. This will increase the likelihood of the PR getting
115 | merged.
116 |
117 | ### Tests
118 |
119 | If the change being proposed alters code (as opposed to only documentation for
120 | example), it is either adding new functionality to faststr or it is fixing
121 | existing, broken functionality. In both of these cases, the pull request should
122 | include one or more tests to ensure that faststr does not regress in the future.
123 |
124 | #### Documentation tests
125 |
126 | Ideally, every API has at least one [documentation test] that demonstrates how to
127 | use the API. Documentation tests are run with `cargo test --doc`. This ensures
128 | that the example is correct and provides additional test coverage.
129 |
130 | The trick to documentation tests is striking a balance between being succinct
131 | for a reader to understand and actually testing the API.
132 |
133 | ### Commits
134 |
135 | It is a recommended best practice to keep your changes as logically grouped as
136 | possible within individual commits. There is no limit to the number of commits
137 | any single Pull Request may have, and many contributors find it easier to review
138 | changes that are split across multiple commits.
139 |
140 | That said, if you have a number of commits that are "checkpoints" and don't
141 | represent a single logical change, please squash those together.
142 |
143 | Note that multiple commits often get squashed when they are landed (see the
144 | notes about [commit squashing](#commit-squashing)).
145 |
146 | We also recommend you to update the [CHANGELOG.md](CHANGELOG.md) of the crate
147 | you are changing together with your commits to keep track of every change.
148 |
149 | #### Commit message guidelines
150 |
151 | A good commit message should describe what changed and why, also known as the
152 | [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/).
153 |
154 | 1. The first line should:
155 |
156 | * contain the type and a short description of the change
157 | (preferably 50 characters or less, and no more than 72 characters)
158 | * be entirely in lowercase with the exception of proper nouns, acronyms, and
159 | the words that refer to code, like function/variable names
160 |
161 | Examples:
162 |
163 | * feat: allow users to set timeout for RPC requests
164 | * fix(codec): fix panic when decoding invalid data
165 |
166 | 2. Keep the second line blank.
167 | 3. Wrap all other lines at 72 columns (except for long URLs).
168 | 4. If your patch fixes an open issue, you can add a reference to it at the end
169 | of the log. Use the `Fixes: #` prefix and the issue number. For other
170 | references use `Refs: #`. `Refs` may include multiple issues, separated by a
171 | comma.
172 |
173 | Examples:
174 |
175 | - `Fixes: #1337`
176 | - `Refs: #1234`
177 |
178 | Sample complete commit message:
179 |
180 | ```txt
181 | fix(codec): fix panic when decoding invalid data
182 |
183 | Body of commit message is a few lines of text, explaining things
184 | in more detail, possibly giving some background about the issue
185 | being fixed, etc.
186 |
187 | The body of the commit message can be several paragraphs, and
188 | please do proper word-wrap and keep columns shorter than about
189 | 72 characters or so. That way, `git log` will show things
190 | nicely even when it is indented.
191 |
192 | Fixes: #1337
193 | Refs: #453, #154
194 | ```
195 |
196 | ### Opening the Pull Request
197 |
198 | From within GitHub, opening a new Pull Request will present you with a
199 | [template] that should be filled out. Please try to do your best at filling out
200 | the details, but feel free to skip parts if you're not sure what to put.
201 |
202 | [template]: .github/PULL_REQUEST_TEMPLATE.md
203 |
204 | ### Discuss and update
205 |
206 | You will probably get feedback or requests for changes to your Pull Request.
207 | This is a big part of the submission process so don't be discouraged! Some
208 | contributors may sign off on the Pull Request right away, others may have
209 | more detailed comments or feedback. This is a necessary part of the process
210 | in order to evaluate whether the changes are correct and necessary.
211 |
212 | **Any community member can review a PR and you might get conflicting feedback**.
213 | Keep an eye out for comments from code owners to provide guidance on conflicting
214 | feedback.
215 |
216 | **Once the PR is open, do not rebase the commits**. See [Commit Squashing](#commit-squashing) for
217 | more details.
218 |
219 | ### Commit Squashing
220 |
221 | In most cases, **do not squash commits that you add to your Pull Request during
222 | the review process**. When the commits in your Pull Request land, they may be
223 | squashed into one commit per logical change. Metadata will be added to the
224 | commit message (including links to the Pull Request, links to relevant issues,
225 | and the names of the reviewers). The commit history of your Pull Request,
226 | however, will stay intact on the Pull Request page.
227 |
228 | ## Reviewing Pull Requests
229 |
230 | **Any faststr community member is welcome to review any pull request**.
231 |
232 | All faststr contributors who choose to review and provide feedback on Pull
233 | Requests have a responsibility to both the project and the individual making the
234 | contribution. Reviews and feedback must be helpful, insightful, and geared
235 | towards improving the contribution as opposed to simply blocking it. If there
236 | are reasons why you feel the PR should not land, explain what those are. Do not
237 | expect to be able to block a Pull Request from advancing simply because you say
238 | "No" without giving an explanation. Be open to having your mind changed. Be open
239 | to working with the contributor to make the Pull Request better.
240 |
241 | Reviews that are dismissive or disrespectful of the contributor or any other
242 | reviewers are strictly counter to the Code of Conduct.
243 |
244 | When reviewing a Pull Request, the primary goals are for the codebase to improve
245 | and for the person submitting the request to succeed. **Even if a Pull Request
246 | does not land, the submitters should come away from the experience feeling like
247 | their effort was not wasted or unappreciated**. Every Pull Request from a new
248 | contributor is an opportunity to grow the community.
249 |
250 | ### Review a bit at a time.
251 |
252 | Do not overwhelm new contributors.
253 |
254 | It is tempting to micro-optimize and make everything about relative performance,
255 | perfect grammar, or exact style matches. Do not succumb to that temptation.
256 |
257 | Focus first on the most significant aspects of the change:
258 |
259 | 1. Does this change make sense for faststr?
260 | 2. Does this change make faststr better, even if only incrementally?
261 | 3. Are there clear bugs or larger scale issues that need attending to?
262 | 4. Is the commit message readable and correct? If it contains a breaking change
263 | is it clear enough?
264 |
265 | Note that only **incremental** improvement is needed to land a PR. This means
266 | that the PR does not need to be perfect, only better than the status quo. Follow
267 | up PRs may be opened to continue iterating.
268 |
269 | When changes are necessary, *request* them, do not *demand* them, and **do not
270 | assume that the submitter already knows how to add a test or run a benchmark**.
271 |
272 | Specific performance optimization techniques, coding styles and conventions
273 | change over time. The first impression you give to a new contributor never does.
274 |
275 | Nits (requests for small changes that are not essential) are fine, but try to
276 | avoid stalling the Pull Request. Most nits can typically be fixed by the faststr
277 | Collaborator landing the Pull Request but they can also be an opportunity for
278 | the contributor to learn a bit more about the project.
279 |
280 | It is always good to clearly indicate nits when you comment: e.g.
281 | `Nit: change foo() to bar(). But this is not blocking.`
282 |
283 | If your comments were addressed but were not folded automatically after new
284 | commits or if they proved to be mistaken, please, [hide them][hiding-a-comment]
285 | with the appropriate reason to keep the conversation flow concise and relevant.
286 |
287 | ### Be aware of the person behind the code
288 |
289 | Be aware that *how* you communicate requests and reviews in your feedback can
290 | have a significant impact on the success of the Pull Request. Yes, we may land
291 | a particular change that makes faststr better, but the individual might just not
292 | want to have anything to do with faststr ever again. The goal is not just having
293 | good code.
294 |
295 | ### Abandoned or Stalled Pull Requests
296 |
297 | If a Pull Request appears to be abandoned or stalled, it is polite to first
298 | check with the contributor to see if they intend to continue the work before
299 | checking if they would mind if you took it over (especially if it just has nits
300 | left). When doing so, it is courteous to give the original contributor credit
301 | for the work they started (either by preserving their name and email address in
302 | the commit log, or by using an `Author: ` meta-data tag in the commit.
303 |
304 | _Adapted from the [Node.js contributing guide][node]_.
305 |
306 | [node]: https://github.com/nodejs/node/blob/master/CONTRIBUTING.md
307 | [hiding-a-comment]: https://help.github.com/articles/managing-disruptive-comments/#hiding-a-comment
308 | [documentation test]: https://doc.rust-lang.org/rustdoc/documentation-tests.html
309 |
310 | ## Keeping track of issues and PRs
311 |
312 | The faststr GitHub repository has a lot of issues and PRs to keep track of. This
313 | section explains the meaning of various labels. The section is primarily targeted
314 | at maintainers. Most contributors aren't able to set these labels.
315 |
316 | ### Area
317 |
318 | The area label describes the crates relevant to this issue or PR.
319 |
320 | - **A-faststr** This issue concerns the `faststr` crate.
321 | - **A-ci** This issue concerns our GitHub Actions setup.
322 |
323 | ### Category
324 |
325 | - **C-bug** This is a bug-report. Bug-fix PRs use `C-enhancement` instead.
326 | - **C-enhancement** This is a PR that adds a new feature or fixes a bug.
327 | - **C-maintenance** This is an issue or PR about stuff such as documentation,
328 | GitHub Actions or code quality.
329 | - **C-feature-request** This is a feature request issue. Implementations of feature
330 | requests use `C-enhancement` instead.
331 | - **C-feature-accepted** If you submit a PR for this feature request, we wont
332 | close it with the reason "we don't want this". Issues with this label should
333 | also have the `C-feature-request` label.
334 | - **C-musing** Stuff like tracking issues or roadmaps. "musings about a better
335 | world".
336 | - **C-proposal** A proposal of some kind, and a request for comments.
337 | - **C-question** A user question.
338 | - **C-request** A non-feature request, e.g. "please document the usage of xx".
339 |
340 | ### Calls for participation
341 |
342 | - **E-help-wanted** Stuff where we want help. Often seen together with `C-bug`
343 | or `C-feature-accepted`.
344 | - **E-easy** This is easy, ranging from quick documentation fixes to stuff you
345 | can do after reading the tutorial on our website.
346 | - **E-medium** This is neither `E-easy` not `E-hard`.
347 | - **E-hard** This either involves very tricky code, is something we don't know
348 | how to solve, or is difficult for some other reason.
349 | - **E-needs-mvce** This bug is missing a minimal complete and verifiable
350 | example.
351 |
352 | The "E-" prefix is the same as used in the Rust compiler repository. Some
353 | issues are missing a difficulty rating, but feel free to ask in our dev
354 | group if you want to know how difficult an issue likely is.
355 |
356 | ### Tags
357 |
358 | There are also some tags that are used to provide additional information.
359 |
360 | - **T-duplicate** This is a duplicate of another issue.
361 | - **T-wontfix** This issue is not a bug, which will not be worked on.
362 | - **T-invalid** This issue is invalid.
363 | - **T-good-first-issue** This issue is good for newcomers.
364 |
365 | ## Versioning Policy
366 |
367 | We adheres the [Semantic Versioning 2.0](https://semver.org/).
368 |
--------------------------------------------------------------------------------
/src/lib.rs:
--------------------------------------------------------------------------------
1 | #![cfg_attr(not(feature = "std"), no_std)]
2 | #![cfg_attr(not(doctest), doc = include_str!("../README.md"))]
3 |
4 | extern crate alloc;
5 |
6 | use alloc::{
7 | borrow::Cow,
8 | string::{String, ToString},
9 | sync::Arc,
10 | vec::Vec,
11 | };
12 | use core::{
13 | borrow::Borrow, cmp::Ordering, convert::Infallible, fmt, hash, iter, ops::Deref, str::FromStr,
14 | };
15 |
16 | use bytes::{Bytes, BytesMut};
17 | use simdutf8::basic::{from_utf8, Utf8Error};
18 |
19 | /// `FastStr` is a string type that try to avoid the cost of clone.
20 | ///
21 | /// **Note:** The memory size of `FastStr` is not `24`, so switching from [`String`] or [`SmolStr`](https://docs.rs/smol_str/latest/smol_str/struct.SmolStr.html) to `FastStr` may not be harmless.
22 | #[derive(Clone)]
23 | pub struct FastStr(Repr);
24 |
25 | #[cfg(all(test, target_pointer_width = "64"))]
26 | mod size_asserts {
27 | static_assertions::assert_eq_size!(super::FastStr, [u8; 40]); // 40 bytes
28 | }
29 |
30 | impl FastStr {
31 | /// Create a new `FastStr` from any type `T` that can be converted to a string slice
32 | /// (e.g., `String`, `&str`, `Arc`, `Arc`).
33 | ///
34 | /// For small strings (up to 24 bytes), this avoids heap allocation, and copies on stack.
35 | #[inline]
36 | pub fn new(text: T) -> Self
37 | where
38 | T: AsRef,
39 | {
40 | Self(Repr::new(text))
41 | }
42 |
43 | /// Create a new inline `FastStr` (up to 24 bytes long) from a string slice `s`.
44 | ///
45 | /// This constructor panics if the length of `s` is greater than 24.
46 | ///
47 | /// Note: the inline length is not guaranteed.
48 | #[inline]
49 | #[doc(hidden)]
50 | #[deprecated(
51 | since = "0.2.13",
52 | note = "The inline threshold is not stable. Please use `FastStr::new()` instead."
53 | )]
54 | pub fn new_inline(s: &str) -> Self {
55 | Self(Repr::new_inline(s))
56 | }
57 |
58 | /// Create a new `FastStr` from a byte slice `v`, returning a
59 | /// `Result` if the bytes are not valid UTF-8.
60 | #[inline]
61 | pub fn new_u8_slice(v: &[u8]) -> Result {
62 | let s = from_utf8(v)?;
63 | Ok(Self::new(s))
64 | }
65 |
66 | /// Create a new `FastStr` from a byte slice `v`. This is an unsafe method because
67 | /// the caller must ensure that the bytes passed to it are valid UTF-8.
68 | ///
69 | /// # Safety
70 | ///
71 | /// `v` must be valid UTF-8.
72 | #[inline]
73 | pub unsafe fn new_u8_slice_unchecked(v: &[u8]) -> Self {
74 | let s = unsafe { core::str::from_utf8_unchecked(v) };
75 | Self::new(s)
76 | }
77 |
78 | /// Create an empty `FastStr`.
79 | #[inline]
80 | pub const fn empty() -> Self {
81 | Self(Repr::empty())
82 | }
83 |
84 | /// Create a new `FastStr` from an `Arc`.
85 | #[inline]
86 | pub fn from_arc_str(s: Arc) -> Self {
87 | if Self::can_inline(&s) {
88 | return Self::new(s);
89 | }
90 | Self(Repr::from_arc_str(s))
91 | }
92 |
93 | /// Create a new `FastStr` from a `String`.
94 | #[inline]
95 | pub fn from_string(s: String) -> Self {
96 | if Self::can_inline(&s) {
97 | return Self::new(s);
98 | }
99 | Self(Repr::from_string(s))
100 | }
101 |
102 | /// Create a new `FastStr` from an `Arc`.
103 | #[inline]
104 | pub fn from_arc_string(s: Arc) -> Self {
105 | if Self::can_inline(&s) {
106 | return Self::new(s.as_str());
107 | }
108 | Self(Repr::from_arc_string(s))
109 | }
110 |
111 | /// Create a new `FastStr` from a `BytesMut` object, returning a
112 | /// `Result` if the bytes are not valid UTF-8.
113 | #[inline]
114 | pub fn from_bytes(b: Bytes) -> Result {
115 | from_utf8(&b)?;
116 | // Safety: we have checked b is utf-8 valid
117 | Ok(unsafe { Self::from_bytes_unchecked(b) })
118 | }
119 |
120 | /// Create a new `FastStr` from a `Bytes` object. This is an unsafe method
121 | /// because the caller must ensure that the bytes passed to it are valid UTF-8.
122 | ///
123 | /// # Safety
124 | ///
125 | /// `b` must be valid UTF-8.
126 | #[inline]
127 | pub unsafe fn from_bytes_unchecked(b: Bytes) -> Self {
128 | let s = core::str::from_utf8_unchecked(&b);
129 | if Self::can_inline(s) {
130 | return Self::new(s);
131 | }
132 | Self(Repr::from_bytes_unchecked(b))
133 | }
134 |
135 | /// Create a new `FastStr` from a `BytesMut` object, returning a
136 | /// `Result` if the bytes are not valid UTF-8.
137 | #[inline]
138 | pub fn from_bytes_mut(b: BytesMut) -> Result {
139 | from_utf8(&b)?;
140 | // Safety: we have checked b is utf-8 valid
141 | Ok(unsafe { Self::from_bytes_mut_unchecked(b) })
142 | }
143 |
144 | /// Create a new `FastStr` from a `BytesMut` object. This is an unsafe method
145 | /// because the caller must ensure that the bytes passed to it are valid UTF-8.
146 | ///
147 | /// # Safety
148 | ///
149 | /// `b` must be valid UTF-8.
150 | #[inline]
151 | pub unsafe fn from_bytes_mut_unchecked(b: BytesMut) -> Self {
152 | let v = b.freeze();
153 | Self::from_bytes_unchecked(v)
154 | }
155 |
156 | /// Create a new `FastStr` from a static string slice.
157 | #[inline]
158 | pub const fn from_static_str(s: &'static str) -> Self {
159 | Self(Repr::StaticStr(s))
160 | }
161 |
162 | /// Create a new `FastStr` from a `Vec`, returning a
163 | /// `Result` if the bytes are not valid UTF-8.
164 | #[inline]
165 | pub fn from_vec_u8(v: Vec) -> Result {
166 | from_utf8(&v)?;
167 | // Safety: we have checked b is utf-8 valid
168 | Ok(unsafe { Self::from_vec_u8_unchecked(v) })
169 | }
170 |
171 | /// Create a new `FastStr` from a `Vec`. This is an unsafe method because
172 | /// the caller must ensure that the bytes passed to it are valid UTF-8.
173 | ///
174 | /// # Safety
175 | ///
176 | /// `v` must be valid UTF-8.
177 | #[inline]
178 | pub unsafe fn from_vec_u8_unchecked(v: Vec) -> Self {
179 | Self::from_bytes_unchecked(v.into())
180 | }
181 |
182 | /// Create a new `FastStr` from a byte slice `v`, returning a
183 | /// `Result` if the bytes are not valid UTF-8.
184 | #[deprecated(
185 | since = "0.2.13",
186 | note = "This method is not really zero-cost. Use `new_u8_slice` instead."
187 | )]
188 | #[inline]
189 | pub fn from_u8_slice(v: &[u8]) -> Result {
190 | Self::new_u8_slice(v)
191 | }
192 |
193 | /// Create a new `FastStr` from a byte slice `v`. This is an unsafe method because
194 | /// the caller must ensure that the bytes passed to it are valid UTF-8.
195 | ///
196 | /// # Safety
197 | ///
198 | /// `v` must be valid UTF-8.
199 | #[deprecated(
200 | since = "0.2.13",
201 | note = "This method is not really zero-cost. Use `new_u8_slice_unchecked` instead."
202 | )]
203 | #[inline]
204 | pub unsafe fn from_u8_slice_unchecked(v: &[u8]) -> Self {
205 | Self::new_u8_slice_unchecked(v)
206 | }
207 | }
208 |
209 | impl FastStr {
210 | /// Return the `FastStr` as a string slice.
211 | #[inline(always)]
212 | pub fn as_str(&self) -> &str {
213 | self.0.as_str()
214 | }
215 |
216 | /// Consumes and converts the `FastStr` into a `Bytes` object.
217 | #[inline(always)]
218 | pub fn into_bytes(self) -> Bytes {
219 | self.0.into_bytes()
220 | }
221 |
222 | /// Return the `FastStr` length.
223 | #[inline(always)]
224 | pub fn len(&self) -> usize {
225 | self.0.len()
226 | }
227 |
228 | /// Return `true` if the `FastStr` is empty.
229 | #[inline(always)]
230 | pub fn is_empty(&self) -> bool {
231 | self.0.is_empty()
232 | }
233 |
234 | /// Return a new `FastStr` that represents a subset of the current string.
235 | ///
236 | /// Note: If the subset is small enough, it will be inlined.
237 | #[inline(always)]
238 | pub fn slice_ref(&self, subset: &str) -> Self {
239 | if subset.len() <= INLINE_CAP {
240 | // Safety: we have checked the length of subset <= `INLINE_CAP`.
241 | return Self(unsafe { Repr::new_inline_impl(subset) });
242 | }
243 | Self(self.0.slice_ref(subset.as_bytes()))
244 | }
245 |
246 | /// Return a new `FastStr` starting at index `start` and ending at index `end`. `[start..end)`
247 | ///
248 | /// # Safety
249 | ///
250 | /// The caller must guarantee that the string between `start` and `end` is valid utf-8.
251 | #[inline(always)]
252 | pub unsafe fn index(&self, start: usize, end: usize) -> Self {
253 | Self(self.0.slice_ref(&self.as_bytes()[start..end]))
254 | }
255 |
256 | /// Consumes and converts the `FastStr` into a `String` at best effort.
257 | #[deprecated(
258 | since = "0.2.13",
259 | note = "This method does not really express the `into` semantic. Use `to_string` instead."
260 | )]
261 | #[inline(always)]
262 | pub fn into_string(self) -> String {
263 | #[allow(deprecated)]
264 | self.0.into_string()
265 | }
266 |
267 | /// If the inner repr of FastStr is a Bytes, then it will be deep cloned and returned as a new
268 | /// FastStr. Otherwise, it will return a new FastStr with the same repr which has no cost.
269 | ///
270 | /// This is used to free the original memory of the Bytes.
271 | ///
272 | /// This is not stable and may be removed or renamed in the future.
273 | #[inline]
274 | #[doc(hidden)]
275 | pub fn deep_clone_bytes(&self) -> Self {
276 | Self(self.0.deep_clone_bytes())
277 | }
278 |
279 | fn from_char_iter>(mut iter: I) -> Self {
280 | let (min_size, _) = iter.size_hint();
281 | if min_size > INLINE_CAP {
282 | let s: String = iter.collect();
283 | return Self(Repr::Bytes(Bytes::from(s)));
284 | }
285 | let mut len = 0;
286 | let mut buf = [0u8; INLINE_CAP];
287 | while let Some(ch) = iter.next() {
288 | let size = ch.len_utf8();
289 | if size + len > INLINE_CAP {
290 | let (min_remaining, _) = iter.size_hint();
291 | let mut s = String::with_capacity(size + len + min_remaining);
292 | s.push_str(unsafe { core::str::from_utf8_unchecked(&buf[..len]) });
293 | s.push(ch);
294 | s.extend(iter);
295 | return Self(Repr::Bytes(Bytes::from(s)));
296 | }
297 | ch.encode_utf8(&mut buf[len..]);
298 | len += size;
299 | }
300 | Self(Repr::Inline { len, buf })
301 | }
302 |
303 | fn can_inline(s: &str) -> bool {
304 | s.len() <= INLINE_CAP
305 | }
306 | }
307 |
308 | impl Default for FastStr {
309 | #[inline]
310 | fn default() -> Self {
311 | Self::empty()
312 | }
313 | }
314 |
315 | impl AsRef<[u8]> for FastStr {
316 | #[inline]
317 | fn as_ref(&self) -> &[u8] {
318 | self.0.as_ref()
319 | }
320 | }
321 |
322 | impl AsRef for FastStr {
323 | #[inline(always)]
324 | fn as_ref(&self) -> &str {
325 | self.as_str()
326 | }
327 | }
328 |
329 | impl Deref for FastStr {
330 | type Target = str;
331 |
332 | #[inline]
333 | fn deref(&self) -> &str {
334 | self.as_str()
335 | }
336 | }
337 |
338 | impl From for String {
339 | #[inline]
340 | fn from(val: FastStr) -> Self {
341 | #[allow(deprecated)]
342 | val.into_string()
343 | }
344 | }
345 |
346 | impl From for Bytes {
347 | #[inline]
348 | fn from(val: FastStr) -> Self {
349 | val.into_bytes()
350 | }
351 | }
352 |
353 | impl PartialEq for FastStr {
354 | #[inline]
355 | fn eq(&self, other: &FastStr) -> bool {
356 | self.as_str() == other.as_str()
357 | }
358 | }
359 |
360 | impl Eq for FastStr {}
361 |
362 | impl PartialEq for FastStr {
363 | #[inline]
364 | fn eq(&self, other: &str) -> bool {
365 | self.as_str() == other
366 | }
367 | }
368 |
369 | impl PartialEq for str {
370 | #[inline]
371 | fn eq(&self, other: &FastStr) -> bool {
372 | other == self
373 | }
374 | }
375 |
376 | impl<'a> PartialEq<&'a str> for FastStr {
377 | #[inline]
378 | fn eq(&self, other: &&'a str) -> bool {
379 | self == *other
380 | }
381 | }
382 |
383 | impl PartialEq for &str {
384 | #[inline]
385 | fn eq(&self, other: &FastStr) -> bool {
386 | *self == other
387 | }
388 | }
389 |
390 | impl PartialEq for FastStr {
391 | #[inline]
392 | fn eq(&self, other: &String) -> bool {
393 | self.as_str() == other
394 | }
395 | }
396 |
397 | impl PartialEq for String {
398 | #[inline]
399 | fn eq(&self, other: &FastStr) -> bool {
400 | other == self
401 | }
402 | }
403 |
404 | impl<'a> PartialEq<&'a String> for FastStr {
405 | #[inline]
406 | fn eq(&self, other: &&'a String) -> bool {
407 | self == *other
408 | }
409 | }
410 |
411 | impl PartialEq for &String {
412 | #[inline]
413 | fn eq(&self, other: &FastStr) -> bool {
414 | *self == other
415 | }
416 | }
417 |
418 | impl Ord for FastStr {
419 | #[inline]
420 | fn cmp(&self, other: &FastStr) -> Ordering {
421 | self.as_str().cmp(other.as_str())
422 | }
423 | }
424 |
425 | impl PartialOrd for FastStr {
426 | #[inline]
427 | fn partial_cmp(&self, other: &FastStr) -> Option {
428 | Some(self.cmp(other))
429 | }
430 | }
431 |
432 | impl hash::Hash for FastStr {
433 | #[inline]
434 | fn hash(&self, hasher: &mut H) {
435 | self.as_str().hash(hasher)
436 | }
437 | }
438 |
439 | impl fmt::Debug for FastStr {
440 | #[inline]
441 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
442 | fmt::Debug::fmt(self.as_str(), f)
443 | }
444 | }
445 |
446 | impl fmt::Display for FastStr {
447 | #[inline]
448 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
449 | fmt::Display::fmt(self.as_str(), f)
450 | }
451 | }
452 |
453 | impl iter::FromIterator for FastStr {
454 | #[inline]
455 | fn from_iter>(iter: I) -> FastStr {
456 | let iter = iter.into_iter();
457 | Self::from_char_iter(iter)
458 | }
459 | }
460 |
461 | fn build_from_str_iter(mut iter: impl Iterator- ) -> FastStr
462 | where
463 | T: AsRef,
464 | String: iter::Extend,
465 | {
466 | let mut len = 0;
467 | let mut buf = [0u8; INLINE_CAP];
468 | while let Some(slice) = iter.next() {
469 | let slice = slice.as_ref();
470 | let size = slice.len();
471 | if size + len > INLINE_CAP {
472 | let mut s = String::with_capacity(size + len);
473 | s.push_str(unsafe { core::str::from_utf8_unchecked(&buf[..len]) });
474 | s.push_str(slice);
475 | s.extend(iter);
476 | return FastStr(Repr::Bytes(Bytes::from(s)));
477 | }
478 | buf[len..][..size].copy_from_slice(slice.as_bytes());
479 | len += size;
480 | }
481 | FastStr(Repr::Inline { len, buf })
482 | }
483 |
484 | impl iter::FromIterator for FastStr {
485 | #[inline]
486 | fn from_iter>(iter: I) -> FastStr {
487 | build_from_str_iter(iter.into_iter())
488 | }
489 | }
490 |
491 | impl<'a> iter::FromIterator<&'a String> for FastStr {
492 | #[inline]
493 | fn from_iter>(iter: I) -> FastStr {
494 | FastStr::from_iter(iter.into_iter().map(|x| x.as_str()))
495 | }
496 | }
497 |
498 | impl<'a> iter::FromIterator<&'a str> for FastStr {
499 | #[inline]
500 | fn from_iter>(iter: I) -> FastStr {
501 | build_from_str_iter(iter.into_iter())
502 | }
503 | }
504 |
505 | impl Borrow for FastStr {
506 | #[inline]
507 | fn borrow(&self) -> &str {
508 | self.as_str()
509 | }
510 | }
511 |
512 | impl FromStr for FastStr {
513 | type Err = Infallible;
514 |
515 | #[inline]
516 | fn from_str(s: &str) -> Result {
517 | Ok(FastStr::new(s))
518 | }
519 | }
520 |
521 | // We need to wait for specilization to be stable to implement this.
522 | // impl From for FastStr
523 | // where
524 | // T: AsRef,
525 | // {
526 | // #[inline]
527 | // fn from(text: T) -> Self {
528 | // Self::new(text)
529 | // }
530 | // }
531 |
532 | impl From> for FastStr {
533 | #[inline]
534 | fn from(val: Arc) -> Self {
535 | Self::from_arc_str(val)
536 | }
537 | }
538 |
539 | impl From for FastStr {
540 | #[inline]
541 | fn from(val: String) -> Self {
542 | Self::from_string(val)
543 | }
544 | }
545 |
546 | impl From> for FastStr {
547 | #[inline]
548 | fn from(val: Arc) -> Self {
549 | Self::from_arc_string(val)
550 | }
551 | }
552 |
553 | impl From<&'static str> for FastStr {
554 | #[inline]
555 | fn from(val: &'static str) -> Self {
556 | Self::from_static_str(val)
557 | }
558 | }
559 |
560 | impl From> for FastStr {
561 | #[inline]
562 | fn from(val: Cow<'static, str>) -> Self {
563 | match val {
564 | Cow::Borrowed(s) => Self::from_static_str(s),
565 | Cow::Owned(s) => Self::from_string(s),
566 | }
567 | }
568 | }
569 |
570 | const INLINE_CAP: usize = 24;
571 |
572 | #[derive(Clone)]
573 | enum Repr {
574 | Empty,
575 | Bytes(Bytes),
576 | ArcStr(Arc),
577 | ArcString(Arc),
578 | StaticStr(&'static str),
579 | Inline { len: usize, buf: [u8; INLINE_CAP] },
580 | }
581 |
582 | impl Repr {
583 | #[inline]
584 | fn new(text: T) -> Self
585 | where
586 | T: AsRef,
587 | {
588 | let text = text.as_ref();
589 | if text.is_empty() {
590 | return Self::Empty;
591 | }
592 | {
593 | let len = text.len();
594 | if len <= INLINE_CAP {
595 | // Safety: we have checked the length of text <= `INLINE_CAP`.
596 | return unsafe { Self::new_inline_impl(text) };
597 | }
598 | }
599 |
600 | Self::Bytes(Bytes::copy_from_slice(text.as_bytes()))
601 | }
602 |
603 | fn new_inline(s: &str) -> Self {
604 | if s.len() > INLINE_CAP {
605 | panic!("[FastStr] string is too long to inline");
606 | }
607 | // Safety: we have checked the length of s <= `INLINE_CAP`.
608 | unsafe { Self::new_inline_impl(s) }
609 | }
610 |
611 | /// # Safety
612 | ///
613 | /// The length of `s` must be <= `INLINE_CAP`.
614 | unsafe fn new_inline_impl(s: &str) -> Self {
615 | let mut buf = [0u8; INLINE_CAP];
616 | core::ptr::copy_nonoverlapping(s.as_ptr(), buf.as_mut_ptr(), s.len());
617 | Self::Inline { len: s.len(), buf }
618 | }
619 |
620 | #[inline]
621 | const fn empty() -> Self {
622 | Self::Empty
623 | }
624 |
625 | #[inline]
626 | fn from_arc_str(s: Arc) -> Self {
627 | Self::ArcStr(s)
628 | }
629 |
630 | #[inline]
631 | fn from_string(s: String) -> Self {
632 | let v = s.into_bytes();
633 | // Safety: s is a `String`, thus we can assume it's valid utf-8
634 | unsafe { Self::from_bytes_unchecked(v.into()) }
635 | }
636 |
637 | #[inline]
638 | fn from_arc_string(s: Arc) -> Self {
639 | match Arc::try_unwrap(s) {
640 | Ok(s) => Self::from_string(s),
641 | Err(s) => Self::ArcString(s),
642 | }
643 | }
644 |
645 | /// Safety: the caller must guarantee that the bytes `v` are valid UTF-8.
646 | #[inline]
647 | unsafe fn from_bytes_unchecked(bytes: Bytes) -> Self {
648 | Self::Bytes(bytes)
649 | }
650 |
651 | #[inline]
652 | fn len(&self) -> usize {
653 | match self {
654 | Self::Empty => 0,
655 | Self::Bytes(bytes) => bytes.len(),
656 | Self::ArcStr(arc_str) => arc_str.len(),
657 | Self::ArcString(arc_string) => arc_string.len(),
658 | Self::StaticStr(s) => s.len(),
659 | Self::Inline { len, .. } => *len,
660 | }
661 | }
662 |
663 | #[inline]
664 | fn is_empty(&self) -> bool {
665 | match self {
666 | Self::Empty => true,
667 | Self::Bytes(bytes) => bytes.is_empty(),
668 | Self::ArcStr(arc_str) => arc_str.is_empty(),
669 | Self::ArcString(arc_string) => arc_string.is_empty(),
670 | Self::StaticStr(s) => s.is_empty(),
671 | Self::Inline { len, .. } => *len == 0,
672 | }
673 | }
674 |
675 | #[inline]
676 | fn as_str(&self) -> &str {
677 | match self {
678 | Self::Empty => "",
679 | // Safety: this is guaranteed by the user when creating the `FastStr`.
680 | Self::Bytes(bytes) => unsafe { core::str::from_utf8_unchecked(bytes) },
681 | Self::ArcStr(arc_str) => arc_str,
682 | Self::ArcString(arc_string) => arc_string,
683 | Self::StaticStr(s) => s,
684 | Self::Inline { len, buf } => unsafe { core::str::from_utf8_unchecked(&buf[..*len]) },
685 | }
686 | }
687 |
688 | #[inline]
689 | #[deprecated]
690 | fn into_string(self) -> String {
691 | match self {
692 | Self::Empty => String::new(),
693 | Self::Bytes(bytes) => unsafe { String::from_utf8_unchecked(bytes.into()) },
694 | Self::ArcStr(arc_str) => arc_str.to_string(),
695 | Self::ArcString(arc_string) => {
696 | Arc::try_unwrap(arc_string).unwrap_or_else(|arc| (*arc).clone())
697 | }
698 | Self::StaticStr(s) => s.to_string(),
699 | Self::Inline { len, buf } => unsafe {
700 | String::from_utf8_unchecked(buf[..len].to_vec())
701 | },
702 | }
703 | }
704 |
705 | #[inline]
706 | fn into_bytes(self) -> Bytes {
707 | match self {
708 | Self::Empty => Bytes::new(),
709 | Self::Bytes(bytes) => bytes,
710 | Self::ArcStr(arc_str) => Bytes::from(arc_str.as_bytes().to_vec()),
711 | Self::ArcString(arc_string) => {
712 | Bytes::from(Arc::try_unwrap(arc_string).unwrap_or_else(|arc| (*arc).clone()))
713 | }
714 | Self::StaticStr(s) => Bytes::from_static(s.as_bytes()),
715 | Self::Inline { len, buf } => Bytes::from(buf[..len].to_vec()),
716 | }
717 | }
718 |
719 | #[inline]
720 | fn deep_clone_bytes(&self) -> Self {
721 | match self {
722 | Self::Empty => Self::Empty,
723 | // Safety: this is guaranteed by the user when creating the `FastStr`.
724 | Self::Bytes(bytes) => unsafe { Self::new(core::str::from_utf8_unchecked(bytes)) },
725 | Self::ArcStr(arc_str) => Self::ArcStr(Arc::clone(arc_str)),
726 | Self::ArcString(arc_string) => Self::ArcString(Arc::clone(arc_string)),
727 | Self::StaticStr(s) => Self::StaticStr(s),
728 | Self::Inline { len, buf } => Self::Inline {
729 | len: *len,
730 | buf: *buf,
731 | },
732 | }
733 | }
734 |
735 | #[inline]
736 | fn slice_ref(&self, subset: &[u8]) -> Self {
737 | if subset.is_empty() {
738 | return Self::Empty;
739 | }
740 | let bytes_p = self.as_ref().as_ptr() as usize;
741 | let bytes_len = self.len();
742 |
743 | let sub_p = subset.as_ptr() as usize;
744 | let sub_len = subset.len();
745 |
746 | assert!(
747 | sub_p >= bytes_p,
748 | "subset pointer ({:p}) is smaller than self pointer ({:p})",
749 | subset.as_ptr(),
750 | self.as_ref().as_ptr(),
751 | );
752 | assert!(
753 | sub_p + sub_len <= bytes_p + bytes_len,
754 | "subset is out of bounds: self = ({:p}, {}), subset = ({:p}, {})",
755 | self.as_ref().as_ptr(),
756 | bytes_len,
757 | subset.as_ptr(),
758 | sub_len,
759 | );
760 |
761 | let sub_offset = sub_p - bytes_p;
762 | match self {
763 | Repr::Empty => panic!("invalid slice ref, self is empty but subset is not"),
764 | Repr::Bytes(b) => Self::Bytes(b.slice_ref(subset)),
765 | Repr::ArcStr(s) => Self::Bytes(Bytes::copy_from_slice(
766 | s[sub_offset..sub_offset + sub_len].as_bytes(),
767 | )),
768 | Repr::ArcString(s) => Self::Bytes(Bytes::copy_from_slice(
769 | s[sub_offset..sub_offset + sub_len].as_bytes(),
770 | )),
771 | Repr::StaticStr(s) => Self::StaticStr(unsafe {
772 | core::str::from_utf8_unchecked(&s.as_bytes()[sub_offset..sub_offset + sub_len])
773 | }),
774 | Repr::Inline { len: _, buf } => Self::Inline {
775 | len: sub_len,
776 | buf: {
777 | let mut new_buf = [0; INLINE_CAP];
778 | new_buf[..sub_len].copy_from_slice(&buf[sub_offset..sub_offset + sub_len]);
779 | new_buf
780 | },
781 | },
782 | }
783 | }
784 | }
785 |
786 | impl AsRef<[u8]> for Repr {
787 | #[inline]
788 | fn as_ref(&self) -> &[u8] {
789 | match self {
790 | Self::Empty => &[],
791 | Self::Bytes(bytes) => bytes.as_ref(),
792 | Self::ArcStr(arc_str) => arc_str.as_bytes(),
793 | Self::ArcString(arc_string) => arc_string.as_bytes(),
794 | Self::StaticStr(s) => s.as_bytes(),
795 | Self::Inline { len, buf } => &buf[..*len],
796 | }
797 | }
798 | }
799 | #[cfg(feature = "redis")]
800 | mod redis;
801 |
802 | #[cfg(feature = "serde")]
803 | mod serde;
804 |
805 | #[cfg(feature = "rkyv")]
806 | mod rkyv;
807 |
808 | #[cfg(feature = "sqlx-mysql")]
809 | mod sqlx_mysql;
810 |
811 | #[cfg(feature = "ts-rs")]
812 | pub mod ts_rs;
813 |
814 | #[cfg(feature = "sea-orm")]
815 | pub mod sea_orm;
816 |
817 | #[cfg(feature = "sqlx-postgres")]
818 | pub mod sqlx_postgres;
819 |
--------------------------------------------------------------------------------
/Cargo.lock:
--------------------------------------------------------------------------------
1 | # This file is automatically @generated by Cargo.
2 | # It is not intended for manual editing.
3 | version = 4
4 |
5 | [[package]]
6 | name = "addr2line"
7 | version = "0.24.2"
8 | source = "registry+https://github.com/rust-lang/crates.io-index"
9 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1"
10 | dependencies = [
11 | "gimli",
12 | ]
13 |
14 | [[package]]
15 | name = "adler2"
16 | version = "2.0.1"
17 | source = "registry+https://github.com/rust-lang/crates.io-index"
18 | checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
19 |
20 | [[package]]
21 | name = "ahash"
22 | version = "0.7.8"
23 | source = "registry+https://github.com/rust-lang/crates.io-index"
24 | checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9"
25 | dependencies = [
26 | "getrandom",
27 | "once_cell",
28 | "version_check",
29 | ]
30 |
31 | [[package]]
32 | name = "aho-corasick"
33 | version = "1.1.3"
34 | source = "registry+https://github.com/rust-lang/crates.io-index"
35 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916"
36 | dependencies = [
37 | "memchr",
38 | ]
39 |
40 | [[package]]
41 | name = "aliasable"
42 | version = "0.1.3"
43 | source = "registry+https://github.com/rust-lang/crates.io-index"
44 | checksum = "250f629c0161ad8107cf89319e990051fae62832fd343083bea452d93e2205fd"
45 |
46 | [[package]]
47 | name = "allocator-api2"
48 | version = "0.2.21"
49 | source = "registry+https://github.com/rust-lang/crates.io-index"
50 | checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923"
51 |
52 | [[package]]
53 | name = "android-tzdata"
54 | version = "0.1.1"
55 | source = "registry+https://github.com/rust-lang/crates.io-index"
56 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0"
57 |
58 | [[package]]
59 | name = "android_system_properties"
60 | version = "0.1.5"
61 | source = "registry+https://github.com/rust-lang/crates.io-index"
62 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311"
63 | dependencies = [
64 | "libc",
65 | ]
66 |
67 | [[package]]
68 | name = "anes"
69 | version = "0.1.6"
70 | source = "registry+https://github.com/rust-lang/crates.io-index"
71 | checksum = "4b46cbb362ab8752921c97e041f5e366ee6297bd428a31275b9fcf1e380f7299"
72 |
73 | [[package]]
74 | name = "anstyle"
75 | version = "1.0.11"
76 | source = "registry+https://github.com/rust-lang/crates.io-index"
77 | checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd"
78 |
79 | [[package]]
80 | name = "arcstr"
81 | version = "1.2.0"
82 | source = "registry+https://github.com/rust-lang/crates.io-index"
83 | checksum = "03918c3dbd7701a85c6b9887732e2921175f26c350b4563841d0958c21d57e6d"
84 |
85 | [[package]]
86 | name = "arrayvec"
87 | version = "0.7.6"
88 | source = "registry+https://github.com/rust-lang/crates.io-index"
89 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50"
90 |
91 | [[package]]
92 | name = "async-stream"
93 | version = "0.3.6"
94 | source = "registry+https://github.com/rust-lang/crates.io-index"
95 | checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476"
96 | dependencies = [
97 | "async-stream-impl",
98 | "futures-core",
99 | "pin-project-lite",
100 | ]
101 |
102 | [[package]]
103 | name = "async-stream-impl"
104 | version = "0.3.6"
105 | source = "registry+https://github.com/rust-lang/crates.io-index"
106 | checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d"
107 | dependencies = [
108 | "proc-macro2",
109 | "quote",
110 | "syn 2.0.106",
111 | ]
112 |
113 | [[package]]
114 | name = "async-trait"
115 | version = "0.1.89"
116 | source = "registry+https://github.com/rust-lang/crates.io-index"
117 | checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb"
118 | dependencies = [
119 | "proc-macro2",
120 | "quote",
121 | "syn 2.0.106",
122 | ]
123 |
124 | [[package]]
125 | name = "atoi"
126 | version = "2.0.0"
127 | source = "registry+https://github.com/rust-lang/crates.io-index"
128 | checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528"
129 | dependencies = [
130 | "num-traits",
131 | ]
132 |
133 | [[package]]
134 | name = "autocfg"
135 | version = "1.5.0"
136 | source = "registry+https://github.com/rust-lang/crates.io-index"
137 | checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
138 |
139 | [[package]]
140 | name = "backtrace"
141 | version = "0.3.75"
142 | source = "registry+https://github.com/rust-lang/crates.io-index"
143 | checksum = "6806a6321ec58106fea15becdad98371e28d92ccbc7c8f1b3b6dd724fe8f1002"
144 | dependencies = [
145 | "addr2line",
146 | "cfg-if",
147 | "libc",
148 | "miniz_oxide",
149 | "object",
150 | "rustc-demangle",
151 | "windows-targets 0.52.6",
152 | ]
153 |
154 | [[package]]
155 | name = "base64"
156 | version = "0.22.1"
157 | source = "registry+https://github.com/rust-lang/crates.io-index"
158 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
159 |
160 | [[package]]
161 | name = "base64ct"
162 | version = "1.8.0"
163 | source = "registry+https://github.com/rust-lang/crates.io-index"
164 | checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
165 |
166 | [[package]]
167 | name = "bigdecimal"
168 | version = "0.4.8"
169 | source = "registry+https://github.com/rust-lang/crates.io-index"
170 | checksum = "1a22f228ab7a1b23027ccc6c350b72868017af7ea8356fbdf19f8d991c690013"
171 | dependencies = [
172 | "autocfg",
173 | "libm",
174 | "num-bigint",
175 | "num-integer",
176 | "num-traits",
177 | "serde",
178 | ]
179 |
180 | [[package]]
181 | name = "bitflags"
182 | version = "2.9.3"
183 | source = "registry+https://github.com/rust-lang/crates.io-index"
184 | checksum = "34efbcccd345379ca2868b2b2c9d3782e9cc58ba87bc7d79d5b53d9c9ae6f25d"
185 | dependencies = [
186 | "serde",
187 | ]
188 |
189 | [[package]]
190 | name = "bitvec"
191 | version = "1.0.1"
192 | source = "registry+https://github.com/rust-lang/crates.io-index"
193 | checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
194 | dependencies = [
195 | "funty",
196 | "radium",
197 | "tap",
198 | "wyz",
199 | ]
200 |
201 | [[package]]
202 | name = "block-buffer"
203 | version = "0.10.4"
204 | source = "registry+https://github.com/rust-lang/crates.io-index"
205 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71"
206 | dependencies = [
207 | "generic-array",
208 | ]
209 |
210 | [[package]]
211 | name = "borsh"
212 | version = "1.5.7"
213 | source = "registry+https://github.com/rust-lang/crates.io-index"
214 | checksum = "ad8646f98db542e39fc66e68a20b2144f6a732636df7c2354e74645faaa433ce"
215 | dependencies = [
216 | "borsh-derive",
217 | "cfg_aliases",
218 | ]
219 |
220 | [[package]]
221 | name = "borsh-derive"
222 | version = "1.5.7"
223 | source = "registry+https://github.com/rust-lang/crates.io-index"
224 | checksum = "fdd1d3c0c2f5833f22386f252fe8ed005c7f59fdcddeef025c01b4c3b9fd9ac3"
225 | dependencies = [
226 | "once_cell",
227 | "proc-macro-crate",
228 | "proc-macro2",
229 | "quote",
230 | "syn 2.0.106",
231 | ]
232 |
233 | [[package]]
234 | name = "bumpalo"
235 | version = "3.19.0"
236 | source = "registry+https://github.com/rust-lang/crates.io-index"
237 | checksum = "46c5e41b57b8bba42a04676d81cb89e9ee8e859a1a66f80a5a72e1cb76b34d43"
238 |
239 | [[package]]
240 | name = "bytecheck"
241 | version = "0.6.12"
242 | source = "registry+https://github.com/rust-lang/crates.io-index"
243 | checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2"
244 | dependencies = [
245 | "bytecheck_derive",
246 | "ptr_meta 0.1.4",
247 | "simdutf8",
248 | ]
249 |
250 | [[package]]
251 | name = "bytecheck_derive"
252 | version = "0.6.12"
253 | source = "registry+https://github.com/rust-lang/crates.io-index"
254 | checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659"
255 | dependencies = [
256 | "proc-macro2",
257 | "quote",
258 | "syn 1.0.109",
259 | ]
260 |
261 | [[package]]
262 | name = "byteorder"
263 | version = "1.5.0"
264 | source = "registry+https://github.com/rust-lang/crates.io-index"
265 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
266 |
267 | [[package]]
268 | name = "bytes"
269 | version = "1.10.1"
270 | source = "registry+https://github.com/rust-lang/crates.io-index"
271 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
272 |
273 | [[package]]
274 | name = "cast"
275 | version = "0.3.0"
276 | source = "registry+https://github.com/rust-lang/crates.io-index"
277 | checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5"
278 |
279 | [[package]]
280 | name = "cc"
281 | version = "1.2.34"
282 | source = "registry+https://github.com/rust-lang/crates.io-index"
283 | checksum = "42bc4aea80032b7bf409b0bc7ccad88853858911b7713a8062fdc0623867bedc"
284 | dependencies = [
285 | "shlex",
286 | ]
287 |
288 | [[package]]
289 | name = "cfg-if"
290 | version = "1.0.3"
291 | source = "registry+https://github.com/rust-lang/crates.io-index"
292 | checksum = "2fd1289c04a9ea8cb22300a459a72a385d7c73d3259e2ed7dcb2af674838cfa9"
293 |
294 | [[package]]
295 | name = "cfg_aliases"
296 | version = "0.2.1"
297 | source = "registry+https://github.com/rust-lang/crates.io-index"
298 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724"
299 |
300 | [[package]]
301 | name = "chrono"
302 | version = "0.4.41"
303 | source = "registry+https://github.com/rust-lang/crates.io-index"
304 | checksum = "c469d952047f47f91b68d1cba3f10d63c11d73e4636f24f08daf0278abf01c4d"
305 | dependencies = [
306 | "android-tzdata",
307 | "iana-time-zone",
308 | "num-traits",
309 | "serde",
310 | "windows-link",
311 | ]
312 |
313 | [[package]]
314 | name = "ciborium"
315 | version = "0.2.2"
316 | source = "registry+https://github.com/rust-lang/crates.io-index"
317 | checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e"
318 | dependencies = [
319 | "ciborium-io",
320 | "ciborium-ll",
321 | "serde",
322 | ]
323 |
324 | [[package]]
325 | name = "ciborium-io"
326 | version = "0.2.2"
327 | source = "registry+https://github.com/rust-lang/crates.io-index"
328 | checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757"
329 |
330 | [[package]]
331 | name = "ciborium-ll"
332 | version = "0.2.2"
333 | source = "registry+https://github.com/rust-lang/crates.io-index"
334 | checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9"
335 | dependencies = [
336 | "ciborium-io",
337 | "half",
338 | ]
339 |
340 | [[package]]
341 | name = "clap"
342 | version = "4.5.45"
343 | source = "registry+https://github.com/rust-lang/crates.io-index"
344 | checksum = "1fc0e74a703892159f5ae7d3aac52c8e6c392f5ae5f359c70b5881d60aaac318"
345 | dependencies = [
346 | "clap_builder",
347 | ]
348 |
349 | [[package]]
350 | name = "clap_builder"
351 | version = "4.5.44"
352 | source = "registry+https://github.com/rust-lang/crates.io-index"
353 | checksum = "b3e7f4214277f3c7aa526a59dd3fbe306a370daee1f8b7b8c987069cd8e888a8"
354 | dependencies = [
355 | "anstyle",
356 | "clap_lex",
357 | ]
358 |
359 | [[package]]
360 | name = "clap_lex"
361 | version = "0.7.5"
362 | source = "registry+https://github.com/rust-lang/crates.io-index"
363 | checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675"
364 |
365 | [[package]]
366 | name = "combine"
367 | version = "4.6.7"
368 | source = "registry+https://github.com/rust-lang/crates.io-index"
369 | checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd"
370 | dependencies = [
371 | "bytes",
372 | "memchr",
373 | ]
374 |
375 | [[package]]
376 | name = "concurrent-queue"
377 | version = "2.5.0"
378 | source = "registry+https://github.com/rust-lang/crates.io-index"
379 | checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973"
380 | dependencies = [
381 | "crossbeam-utils",
382 | ]
383 |
384 | [[package]]
385 | name = "const-oid"
386 | version = "0.9.6"
387 | source = "registry+https://github.com/rust-lang/crates.io-index"
388 | checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
389 |
390 | [[package]]
391 | name = "core-foundation-sys"
392 | version = "0.8.7"
393 | source = "registry+https://github.com/rust-lang/crates.io-index"
394 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
395 |
396 | [[package]]
397 | name = "cpufeatures"
398 | version = "0.2.17"
399 | source = "registry+https://github.com/rust-lang/crates.io-index"
400 | checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280"
401 | dependencies = [
402 | "libc",
403 | ]
404 |
405 | [[package]]
406 | name = "crc"
407 | version = "3.3.0"
408 | source = "registry+https://github.com/rust-lang/crates.io-index"
409 | checksum = "9710d3b3739c2e349eb44fe848ad0b7c8cb1e42bd87ee49371df2f7acaf3e675"
410 | dependencies = [
411 | "crc-catalog",
412 | ]
413 |
414 | [[package]]
415 | name = "crc-catalog"
416 | version = "2.4.0"
417 | source = "registry+https://github.com/rust-lang/crates.io-index"
418 | checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
419 |
420 | [[package]]
421 | name = "criterion"
422 | version = "0.7.0"
423 | source = "registry+https://github.com/rust-lang/crates.io-index"
424 | checksum = "e1c047a62b0cc3e145fa84415a3191f628e980b194c2755aa12300a4e6cbd928"
425 | dependencies = [
426 | "anes",
427 | "cast",
428 | "ciborium",
429 | "clap",
430 | "criterion-plot",
431 | "itertools",
432 | "num-traits",
433 | "oorandom",
434 | "plotters",
435 | "rayon",
436 | "regex",
437 | "serde",
438 | "serde_json",
439 | "tinytemplate",
440 | "walkdir",
441 | ]
442 |
443 | [[package]]
444 | name = "criterion-plot"
445 | version = "0.6.0"
446 | source = "registry+https://github.com/rust-lang/crates.io-index"
447 | checksum = "9b1bcc0dc7dfae599d84ad0b1a55f80cde8af3725da8313b528da95ef783e338"
448 | dependencies = [
449 | "cast",
450 | "itertools",
451 | ]
452 |
453 | [[package]]
454 | name = "crossbeam-deque"
455 | version = "0.8.6"
456 | source = "registry+https://github.com/rust-lang/crates.io-index"
457 | checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
458 | dependencies = [
459 | "crossbeam-epoch",
460 | "crossbeam-utils",
461 | ]
462 |
463 | [[package]]
464 | name = "crossbeam-epoch"
465 | version = "0.9.18"
466 | source = "registry+https://github.com/rust-lang/crates.io-index"
467 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
468 | dependencies = [
469 | "crossbeam-utils",
470 | ]
471 |
472 | [[package]]
473 | name = "crossbeam-queue"
474 | version = "0.3.12"
475 | source = "registry+https://github.com/rust-lang/crates.io-index"
476 | checksum = "0f58bbc28f91df819d0aa2a2c00cd19754769c2fad90579b3592b1c9ba7a3115"
477 | dependencies = [
478 | "crossbeam-utils",
479 | ]
480 |
481 | [[package]]
482 | name = "crossbeam-utils"
483 | version = "0.8.21"
484 | source = "registry+https://github.com/rust-lang/crates.io-index"
485 | checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28"
486 |
487 | [[package]]
488 | name = "crunchy"
489 | version = "0.2.4"
490 | source = "registry+https://github.com/rust-lang/crates.io-index"
491 | checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
492 |
493 | [[package]]
494 | name = "crypto-common"
495 | version = "0.1.6"
496 | source = "registry+https://github.com/rust-lang/crates.io-index"
497 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3"
498 | dependencies = [
499 | "generic-array",
500 | "typenum",
501 | ]
502 |
503 | [[package]]
504 | name = "debugger-example"
505 | version = "0.1.0"
506 | dependencies = [
507 | "faststr",
508 | ]
509 |
510 | [[package]]
511 | name = "der"
512 | version = "0.7.10"
513 | source = "registry+https://github.com/rust-lang/crates.io-index"
514 | checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
515 | dependencies = [
516 | "const-oid",
517 | "pem-rfc7468",
518 | "zeroize",
519 | ]
520 |
521 | [[package]]
522 | name = "deranged"
523 | version = "0.4.0"
524 | source = "registry+https://github.com/rust-lang/crates.io-index"
525 | checksum = "9c9e6a11ca8224451684bc0d7d5a7adbf8f2fd6887261a1cfc3c0432f9d4068e"
526 | dependencies = [
527 | "powerfmt",
528 | "serde",
529 | ]
530 |
531 | [[package]]
532 | name = "digest"
533 | version = "0.10.7"
534 | source = "registry+https://github.com/rust-lang/crates.io-index"
535 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
536 | dependencies = [
537 | "block-buffer",
538 | "const-oid",
539 | "crypto-common",
540 | "subtle",
541 | ]
542 |
543 | [[package]]
544 | name = "displaydoc"
545 | version = "0.2.5"
546 | source = "registry+https://github.com/rust-lang/crates.io-index"
547 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0"
548 | dependencies = [
549 | "proc-macro2",
550 | "quote",
551 | "syn 2.0.106",
552 | ]
553 |
554 | [[package]]
555 | name = "dotenvy"
556 | version = "0.15.7"
557 | source = "registry+https://github.com/rust-lang/crates.io-index"
558 | checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b"
559 |
560 | [[package]]
561 | name = "either"
562 | version = "1.15.0"
563 | source = "registry+https://github.com/rust-lang/crates.io-index"
564 | checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719"
565 | dependencies = [
566 | "serde",
567 | ]
568 |
569 | [[package]]
570 | name = "equivalent"
571 | version = "1.0.2"
572 | source = "registry+https://github.com/rust-lang/crates.io-index"
573 | checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f"
574 |
575 | [[package]]
576 | name = "etcetera"
577 | version = "0.8.0"
578 | source = "registry+https://github.com/rust-lang/crates.io-index"
579 | checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943"
580 | dependencies = [
581 | "cfg-if",
582 | "home",
583 | "windows-sys 0.48.0",
584 | ]
585 |
586 | [[package]]
587 | name = "event-listener"
588 | version = "5.4.1"
589 | source = "registry+https://github.com/rust-lang/crates.io-index"
590 | checksum = "e13b66accf52311f30a0db42147dadea9850cb48cd070028831ae5f5d4b856ab"
591 | dependencies = [
592 | "concurrent-queue",
593 | "parking",
594 | "pin-project-lite",
595 | ]
596 |
597 | [[package]]
598 | name = "faststr"
599 | version = "0.2.32"
600 | dependencies = [
601 | "bytes",
602 | "criterion",
603 | "itoa",
604 | "redis",
605 | "rkyv 0.8.11",
606 | "ryu",
607 | "sea-orm",
608 | "serde",
609 | "simdutf8",
610 | "sqlx",
611 | "sqlx-mysql",
612 | "sqlx-postgres",
613 | "static_assertions",
614 | "tokio",
615 | "ts-rs",
616 | ]
617 |
618 | [[package]]
619 | name = "flume"
620 | version = "0.11.1"
621 | source = "registry+https://github.com/rust-lang/crates.io-index"
622 | checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095"
623 | dependencies = [
624 | "futures-core",
625 | "futures-sink",
626 | "spin",
627 | ]
628 |
629 | [[package]]
630 | name = "foldhash"
631 | version = "0.1.5"
632 | source = "registry+https://github.com/rust-lang/crates.io-index"
633 | checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2"
634 |
635 | [[package]]
636 | name = "form_urlencoded"
637 | version = "1.2.2"
638 | source = "registry+https://github.com/rust-lang/crates.io-index"
639 | checksum = "cb4cb245038516f5f85277875cdaa4f7d2c9a0fa0468de06ed190163b1581fcf"
640 | dependencies = [
641 | "percent-encoding",
642 | ]
643 |
644 | [[package]]
645 | name = "funty"
646 | version = "2.0.0"
647 | source = "registry+https://github.com/rust-lang/crates.io-index"
648 | checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
649 |
650 | [[package]]
651 | name = "futures-channel"
652 | version = "0.3.31"
653 | source = "registry+https://github.com/rust-lang/crates.io-index"
654 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10"
655 | dependencies = [
656 | "futures-core",
657 | "futures-sink",
658 | ]
659 |
660 | [[package]]
661 | name = "futures-core"
662 | version = "0.3.31"
663 | source = "registry+https://github.com/rust-lang/crates.io-index"
664 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e"
665 |
666 | [[package]]
667 | name = "futures-executor"
668 | version = "0.3.31"
669 | source = "registry+https://github.com/rust-lang/crates.io-index"
670 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f"
671 | dependencies = [
672 | "futures-core",
673 | "futures-task",
674 | "futures-util",
675 | ]
676 |
677 | [[package]]
678 | name = "futures-intrusive"
679 | version = "0.5.0"
680 | source = "registry+https://github.com/rust-lang/crates.io-index"
681 | checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f"
682 | dependencies = [
683 | "futures-core",
684 | "lock_api",
685 | "parking_lot",
686 | ]
687 |
688 | [[package]]
689 | name = "futures-io"
690 | version = "0.3.31"
691 | source = "registry+https://github.com/rust-lang/crates.io-index"
692 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6"
693 |
694 | [[package]]
695 | name = "futures-sink"
696 | version = "0.3.31"
697 | source = "registry+https://github.com/rust-lang/crates.io-index"
698 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7"
699 |
700 | [[package]]
701 | name = "futures-task"
702 | version = "0.3.31"
703 | source = "registry+https://github.com/rust-lang/crates.io-index"
704 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988"
705 |
706 | [[package]]
707 | name = "futures-util"
708 | version = "0.3.31"
709 | source = "registry+https://github.com/rust-lang/crates.io-index"
710 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81"
711 | dependencies = [
712 | "futures-core",
713 | "futures-io",
714 | "futures-sink",
715 | "futures-task",
716 | "memchr",
717 | "pin-project-lite",
718 | "pin-utils",
719 | "slab",
720 | ]
721 |
722 | [[package]]
723 | name = "generic-array"
724 | version = "0.14.7"
725 | source = "registry+https://github.com/rust-lang/crates.io-index"
726 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a"
727 | dependencies = [
728 | "typenum",
729 | "version_check",
730 | ]
731 |
732 | [[package]]
733 | name = "getrandom"
734 | version = "0.2.16"
735 | source = "registry+https://github.com/rust-lang/crates.io-index"
736 | checksum = "335ff9f135e4384c8150d6f27c6daed433577f86b4750418338c01a1a2528592"
737 | dependencies = [
738 | "cfg-if",
739 | "libc",
740 | "wasi",
741 | ]
742 |
743 | [[package]]
744 | name = "gimli"
745 | version = "0.31.1"
746 | source = "registry+https://github.com/rust-lang/crates.io-index"
747 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f"
748 |
749 | [[package]]
750 | name = "half"
751 | version = "2.6.0"
752 | source = "registry+https://github.com/rust-lang/crates.io-index"
753 | checksum = "459196ed295495a68f7d7fe1d84f6c4b7ff0e21fe3017b2f283c6fac3ad803c9"
754 | dependencies = [
755 | "cfg-if",
756 | "crunchy",
757 | ]
758 |
759 | [[package]]
760 | name = "hashbrown"
761 | version = "0.12.3"
762 | source = "registry+https://github.com/rust-lang/crates.io-index"
763 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888"
764 | dependencies = [
765 | "ahash",
766 | ]
767 |
768 | [[package]]
769 | name = "hashbrown"
770 | version = "0.15.5"
771 | source = "registry+https://github.com/rust-lang/crates.io-index"
772 | checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1"
773 | dependencies = [
774 | "allocator-api2",
775 | "equivalent",
776 | "foldhash",
777 | ]
778 |
779 | [[package]]
780 | name = "hashlink"
781 | version = "0.10.0"
782 | source = "registry+https://github.com/rust-lang/crates.io-index"
783 | checksum = "7382cf6263419f2d8df38c55d7da83da5c18aef87fc7a7fc1fb1e344edfe14c1"
784 | dependencies = [
785 | "hashbrown 0.15.5",
786 | ]
787 |
788 | [[package]]
789 | name = "heck"
790 | version = "0.4.1"
791 | source = "registry+https://github.com/rust-lang/crates.io-index"
792 | checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8"
793 |
794 | [[package]]
795 | name = "heck"
796 | version = "0.5.0"
797 | source = "registry+https://github.com/rust-lang/crates.io-index"
798 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
799 |
800 | [[package]]
801 | name = "hex"
802 | version = "0.4.3"
803 | source = "registry+https://github.com/rust-lang/crates.io-index"
804 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70"
805 |
806 | [[package]]
807 | name = "hkdf"
808 | version = "0.12.4"
809 | source = "registry+https://github.com/rust-lang/crates.io-index"
810 | checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7"
811 | dependencies = [
812 | "hmac",
813 | ]
814 |
815 | [[package]]
816 | name = "hmac"
817 | version = "0.12.1"
818 | source = "registry+https://github.com/rust-lang/crates.io-index"
819 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e"
820 | dependencies = [
821 | "digest",
822 | ]
823 |
824 | [[package]]
825 | name = "home"
826 | version = "0.5.11"
827 | source = "registry+https://github.com/rust-lang/crates.io-index"
828 | checksum = "589533453244b0995c858700322199b2becb13b627df2851f64a2775d024abcf"
829 | dependencies = [
830 | "windows-sys 0.59.0",
831 | ]
832 |
833 | [[package]]
834 | name = "iana-time-zone"
835 | version = "0.1.63"
836 | source = "registry+https://github.com/rust-lang/crates.io-index"
837 | checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8"
838 | dependencies = [
839 | "android_system_properties",
840 | "core-foundation-sys",
841 | "iana-time-zone-haiku",
842 | "js-sys",
843 | "log",
844 | "wasm-bindgen",
845 | "windows-core",
846 | ]
847 |
848 | [[package]]
849 | name = "iana-time-zone-haiku"
850 | version = "0.1.2"
851 | source = "registry+https://github.com/rust-lang/crates.io-index"
852 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f"
853 | dependencies = [
854 | "cc",
855 | ]
856 |
857 | [[package]]
858 | name = "icu_collections"
859 | version = "2.0.0"
860 | source = "registry+https://github.com/rust-lang/crates.io-index"
861 | checksum = "200072f5d0e3614556f94a9930d5dc3e0662a652823904c3a75dc3b0af7fee47"
862 | dependencies = [
863 | "displaydoc",
864 | "potential_utf",
865 | "yoke",
866 | "zerofrom",
867 | "zerovec",
868 | ]
869 |
870 | [[package]]
871 | name = "icu_locale_core"
872 | version = "2.0.0"
873 | source = "registry+https://github.com/rust-lang/crates.io-index"
874 | checksum = "0cde2700ccaed3872079a65fb1a78f6c0a36c91570f28755dda67bc8f7d9f00a"
875 | dependencies = [
876 | "displaydoc",
877 | "litemap",
878 | "tinystr",
879 | "writeable",
880 | "zerovec",
881 | ]
882 |
883 | [[package]]
884 | name = "icu_normalizer"
885 | version = "2.0.0"
886 | source = "registry+https://github.com/rust-lang/crates.io-index"
887 | checksum = "436880e8e18df4d7bbc06d58432329d6458cc84531f7ac5f024e93deadb37979"
888 | dependencies = [
889 | "displaydoc",
890 | "icu_collections",
891 | "icu_normalizer_data",
892 | "icu_properties",
893 | "icu_provider",
894 | "smallvec",
895 | "zerovec",
896 | ]
897 |
898 | [[package]]
899 | name = "icu_normalizer_data"
900 | version = "2.0.0"
901 | source = "registry+https://github.com/rust-lang/crates.io-index"
902 | checksum = "00210d6893afc98edb752b664b8890f0ef174c8adbb8d0be9710fa66fbbf72d3"
903 |
904 | [[package]]
905 | name = "icu_properties"
906 | version = "2.0.1"
907 | source = "registry+https://github.com/rust-lang/crates.io-index"
908 | checksum = "016c619c1eeb94efb86809b015c58f479963de65bdb6253345c1a1276f22e32b"
909 | dependencies = [
910 | "displaydoc",
911 | "icu_collections",
912 | "icu_locale_core",
913 | "icu_properties_data",
914 | "icu_provider",
915 | "potential_utf",
916 | "zerotrie",
917 | "zerovec",
918 | ]
919 |
920 | [[package]]
921 | name = "icu_properties_data"
922 | version = "2.0.1"
923 | source = "registry+https://github.com/rust-lang/crates.io-index"
924 | checksum = "298459143998310acd25ffe6810ed544932242d3f07083eee1084d83a71bd632"
925 |
926 | [[package]]
927 | name = "icu_provider"
928 | version = "2.0.0"
929 | source = "registry+https://github.com/rust-lang/crates.io-index"
930 | checksum = "03c80da27b5f4187909049ee2d72f276f0d9f99a42c306bd0131ecfe04d8e5af"
931 | dependencies = [
932 | "displaydoc",
933 | "icu_locale_core",
934 | "stable_deref_trait",
935 | "tinystr",
936 | "writeable",
937 | "yoke",
938 | "zerofrom",
939 | "zerotrie",
940 | "zerovec",
941 | ]
942 |
943 | [[package]]
944 | name = "idna"
945 | version = "1.1.0"
946 | source = "registry+https://github.com/rust-lang/crates.io-index"
947 | checksum = "3b0875f23caa03898994f6ddc501886a45c7d3d62d04d2d90788d47be1b1e4de"
948 | dependencies = [
949 | "idna_adapter",
950 | "smallvec",
951 | "utf8_iter",
952 | ]
953 |
954 | [[package]]
955 | name = "idna_adapter"
956 | version = "1.2.1"
957 | source = "registry+https://github.com/rust-lang/crates.io-index"
958 | checksum = "3acae9609540aa318d1bc588455225fb2085b9ed0c4f6bd0d9d5bcd86f1a0344"
959 | dependencies = [
960 | "icu_normalizer",
961 | "icu_properties",
962 | ]
963 |
964 | [[package]]
965 | name = "indexmap"
966 | version = "2.11.0"
967 | source = "registry+https://github.com/rust-lang/crates.io-index"
968 | checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9"
969 | dependencies = [
970 | "equivalent",
971 | "hashbrown 0.15.5",
972 | ]
973 |
974 | [[package]]
975 | name = "inherent"
976 | version = "1.0.12"
977 | source = "registry+https://github.com/rust-lang/crates.io-index"
978 | checksum = "6c38228f24186d9cc68c729accb4d413be9eaed6ad07ff79e0270d9e56f3de13"
979 | dependencies = [
980 | "proc-macro2",
981 | "quote",
982 | "syn 2.0.106",
983 | ]
984 |
985 | [[package]]
986 | name = "io-uring"
987 | version = "0.7.10"
988 | source = "registry+https://github.com/rust-lang/crates.io-index"
989 | checksum = "046fa2d4d00aea763528b4950358d0ead425372445dc8ff86312b3c69ff7727b"
990 | dependencies = [
991 | "bitflags",
992 | "cfg-if",
993 | "libc",
994 | ]
995 |
996 | [[package]]
997 | name = "itertools"
998 | version = "0.13.0"
999 | source = "registry+https://github.com/rust-lang/crates.io-index"
1000 | checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186"
1001 | dependencies = [
1002 | "either",
1003 | ]
1004 |
1005 | [[package]]
1006 | name = "itoa"
1007 | version = "1.0.15"
1008 | source = "registry+https://github.com/rust-lang/crates.io-index"
1009 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c"
1010 |
1011 | [[package]]
1012 | name = "js-sys"
1013 | version = "0.3.77"
1014 | source = "registry+https://github.com/rust-lang/crates.io-index"
1015 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f"
1016 | dependencies = [
1017 | "once_cell",
1018 | "wasm-bindgen",
1019 | ]
1020 |
1021 | [[package]]
1022 | name = "lazy_static"
1023 | version = "1.5.0"
1024 | source = "registry+https://github.com/rust-lang/crates.io-index"
1025 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe"
1026 | dependencies = [
1027 | "spin",
1028 | ]
1029 |
1030 | [[package]]
1031 | name = "libc"
1032 | version = "0.2.175"
1033 | source = "registry+https://github.com/rust-lang/crates.io-index"
1034 | checksum = "6a82ae493e598baaea5209805c49bbf2ea7de956d50d7da0da1164f9c6d28543"
1035 |
1036 | [[package]]
1037 | name = "libm"
1038 | version = "0.2.15"
1039 | source = "registry+https://github.com/rust-lang/crates.io-index"
1040 | checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
1041 |
1042 | [[package]]
1043 | name = "libredox"
1044 | version = "0.1.9"
1045 | source = "registry+https://github.com/rust-lang/crates.io-index"
1046 | checksum = "391290121bad3d37fbddad76d8f5d1c1c314cfc646d143d7e07a3086ddff0ce3"
1047 | dependencies = [
1048 | "bitflags",
1049 | "libc",
1050 | "redox_syscall",
1051 | ]
1052 |
1053 | [[package]]
1054 | name = "libsqlite3-sys"
1055 | version = "0.30.1"
1056 | source = "registry+https://github.com/rust-lang/crates.io-index"
1057 | checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
1058 | dependencies = [
1059 | "pkg-config",
1060 | "vcpkg",
1061 | ]
1062 |
1063 | [[package]]
1064 | name = "litemap"
1065 | version = "0.8.0"
1066 | source = "registry+https://github.com/rust-lang/crates.io-index"
1067 | checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
1068 |
1069 | [[package]]
1070 | name = "lock_api"
1071 | version = "0.4.13"
1072 | source = "registry+https://github.com/rust-lang/crates.io-index"
1073 | checksum = "96936507f153605bddfcda068dd804796c84324ed2510809e5b2a624c81da765"
1074 | dependencies = [
1075 | "autocfg",
1076 | "scopeguard",
1077 | ]
1078 |
1079 | [[package]]
1080 | name = "log"
1081 | version = "0.4.27"
1082 | source = "registry+https://github.com/rust-lang/crates.io-index"
1083 | checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94"
1084 |
1085 | [[package]]
1086 | name = "md-5"
1087 | version = "0.10.6"
1088 | source = "registry+https://github.com/rust-lang/crates.io-index"
1089 | checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
1090 | dependencies = [
1091 | "cfg-if",
1092 | "digest",
1093 | ]
1094 |
1095 | [[package]]
1096 | name = "memchr"
1097 | version = "2.7.5"
1098 | source = "registry+https://github.com/rust-lang/crates.io-index"
1099 | checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0"
1100 |
1101 | [[package]]
1102 | name = "miniz_oxide"
1103 | version = "0.8.9"
1104 | source = "registry+https://github.com/rust-lang/crates.io-index"
1105 | checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
1106 | dependencies = [
1107 | "adler2",
1108 | ]
1109 |
1110 | [[package]]
1111 | name = "mio"
1112 | version = "1.0.4"
1113 | source = "registry+https://github.com/rust-lang/crates.io-index"
1114 | checksum = "78bed444cc8a2160f01cbcf811ef18cac863ad68ae8ca62092e8db51d51c761c"
1115 | dependencies = [
1116 | "libc",
1117 | "wasi",
1118 | "windows-sys 0.59.0",
1119 | ]
1120 |
1121 | [[package]]
1122 | name = "munge"
1123 | version = "0.4.6"
1124 | source = "registry+https://github.com/rust-lang/crates.io-index"
1125 | checksum = "d7feb0b48aa0a25f9fe0899482c6e1379ee7a11b24a53073eacdecb9adb6dc60"
1126 | dependencies = [
1127 | "munge_macro",
1128 | ]
1129 |
1130 | [[package]]
1131 | name = "munge_macro"
1132 | version = "0.4.6"
1133 | source = "registry+https://github.com/rust-lang/crates.io-index"
1134 | checksum = "f2e3795a5d2da581a8b252fec6022eee01aea10161a4d1bf237d4cbe47f7e988"
1135 | dependencies = [
1136 | "proc-macro2",
1137 | "quote",
1138 | "syn 2.0.106",
1139 | ]
1140 |
1141 | [[package]]
1142 | name = "num-bigint"
1143 | version = "0.4.6"
1144 | source = "registry+https://github.com/rust-lang/crates.io-index"
1145 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
1146 | dependencies = [
1147 | "num-integer",
1148 | "num-traits",
1149 | ]
1150 |
1151 | [[package]]
1152 | name = "num-bigint-dig"
1153 | version = "0.8.4"
1154 | source = "registry+https://github.com/rust-lang/crates.io-index"
1155 | checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151"
1156 | dependencies = [
1157 | "byteorder",
1158 | "lazy_static",
1159 | "libm",
1160 | "num-integer",
1161 | "num-iter",
1162 | "num-traits",
1163 | "rand",
1164 | "smallvec",
1165 | "zeroize",
1166 | ]
1167 |
1168 | [[package]]
1169 | name = "num-conv"
1170 | version = "0.1.0"
1171 | source = "registry+https://github.com/rust-lang/crates.io-index"
1172 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9"
1173 |
1174 | [[package]]
1175 | name = "num-integer"
1176 | version = "0.1.46"
1177 | source = "registry+https://github.com/rust-lang/crates.io-index"
1178 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
1179 | dependencies = [
1180 | "num-traits",
1181 | ]
1182 |
1183 | [[package]]
1184 | name = "num-iter"
1185 | version = "0.1.45"
1186 | source = "registry+https://github.com/rust-lang/crates.io-index"
1187 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf"
1188 | dependencies = [
1189 | "autocfg",
1190 | "num-integer",
1191 | "num-traits",
1192 | ]
1193 |
1194 | [[package]]
1195 | name = "num-traits"
1196 | version = "0.2.19"
1197 | source = "registry+https://github.com/rust-lang/crates.io-index"
1198 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
1199 | dependencies = [
1200 | "autocfg",
1201 | "libm",
1202 | ]
1203 |
1204 | [[package]]
1205 | name = "object"
1206 | version = "0.36.7"
1207 | source = "registry+https://github.com/rust-lang/crates.io-index"
1208 | checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87"
1209 | dependencies = [
1210 | "memchr",
1211 | ]
1212 |
1213 | [[package]]
1214 | name = "once_cell"
1215 | version = "1.21.3"
1216 | source = "registry+https://github.com/rust-lang/crates.io-index"
1217 | checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d"
1218 |
1219 | [[package]]
1220 | name = "oorandom"
1221 | version = "11.1.5"
1222 | source = "registry+https://github.com/rust-lang/crates.io-index"
1223 | checksum = "d6790f58c7ff633d8771f42965289203411a5e5c68388703c06e14f24770b41e"
1224 |
1225 | [[package]]
1226 | name = "ordered-float"
1227 | version = "4.6.0"
1228 | source = "registry+https://github.com/rust-lang/crates.io-index"
1229 | checksum = "7bb71e1b3fa6ca1c61f383464aaf2bb0e2f8e772a1f01d486832464de363b951"
1230 | dependencies = [
1231 | "num-traits",
1232 | ]
1233 |
1234 | [[package]]
1235 | name = "ouroboros"
1236 | version = "0.18.5"
1237 | source = "registry+https://github.com/rust-lang/crates.io-index"
1238 | checksum = "1e0f050db9c44b97a94723127e6be766ac5c340c48f2c4bb3ffa11713744be59"
1239 | dependencies = [
1240 | "aliasable",
1241 | "ouroboros_macro",
1242 | "static_assertions",
1243 | ]
1244 |
1245 | [[package]]
1246 | name = "ouroboros_macro"
1247 | version = "0.18.5"
1248 | source = "registry+https://github.com/rust-lang/crates.io-index"
1249 | checksum = "3c7028bdd3d43083f6d8d4d5187680d0d3560d54df4cc9d752005268b41e64d0"
1250 | dependencies = [
1251 | "heck 0.4.1",
1252 | "proc-macro2",
1253 | "proc-macro2-diagnostics",
1254 | "quote",
1255 | "syn 2.0.106",
1256 | ]
1257 |
1258 | [[package]]
1259 | name = "parking"
1260 | version = "2.2.1"
1261 | source = "registry+https://github.com/rust-lang/crates.io-index"
1262 | checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba"
1263 |
1264 | [[package]]
1265 | name = "parking_lot"
1266 | version = "0.12.4"
1267 | source = "registry+https://github.com/rust-lang/crates.io-index"
1268 | checksum = "70d58bf43669b5795d1576d0641cfb6fbb2057bf629506267a92807158584a13"
1269 | dependencies = [
1270 | "lock_api",
1271 | "parking_lot_core",
1272 | ]
1273 |
1274 | [[package]]
1275 | name = "parking_lot_core"
1276 | version = "0.9.11"
1277 | source = "registry+https://github.com/rust-lang/crates.io-index"
1278 | checksum = "bc838d2a56b5b1a6c25f55575dfc605fabb63bb2365f6c2353ef9159aa69e4a5"
1279 | dependencies = [
1280 | "cfg-if",
1281 | "libc",
1282 | "redox_syscall",
1283 | "smallvec",
1284 | "windows-targets 0.52.6",
1285 | ]
1286 |
1287 | [[package]]
1288 | name = "pem-rfc7468"
1289 | version = "0.7.0"
1290 | source = "registry+https://github.com/rust-lang/crates.io-index"
1291 | checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
1292 | dependencies = [
1293 | "base64ct",
1294 | ]
1295 |
1296 | [[package]]
1297 | name = "percent-encoding"
1298 | version = "2.3.2"
1299 | source = "registry+https://github.com/rust-lang/crates.io-index"
1300 | checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
1301 |
1302 | [[package]]
1303 | name = "pgvector"
1304 | version = "0.4.1"
1305 | source = "registry+https://github.com/rust-lang/crates.io-index"
1306 | checksum = "fc58e2d255979a31caa7cabfa7aac654af0354220719ab7a68520ae7a91e8c0b"
1307 | dependencies = [
1308 | "serde",
1309 | ]
1310 |
1311 | [[package]]
1312 | name = "pin-project-lite"
1313 | version = "0.2.16"
1314 | source = "registry+https://github.com/rust-lang/crates.io-index"
1315 | checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b"
1316 |
1317 | [[package]]
1318 | name = "pin-utils"
1319 | version = "0.1.0"
1320 | source = "registry+https://github.com/rust-lang/crates.io-index"
1321 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
1322 |
1323 | [[package]]
1324 | name = "pkcs1"
1325 | version = "0.7.5"
1326 | source = "registry+https://github.com/rust-lang/crates.io-index"
1327 | checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f"
1328 | dependencies = [
1329 | "der",
1330 | "pkcs8",
1331 | "spki",
1332 | ]
1333 |
1334 | [[package]]
1335 | name = "pkcs8"
1336 | version = "0.10.2"
1337 | source = "registry+https://github.com/rust-lang/crates.io-index"
1338 | checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7"
1339 | dependencies = [
1340 | "der",
1341 | "spki",
1342 | ]
1343 |
1344 | [[package]]
1345 | name = "pkg-config"
1346 | version = "0.3.32"
1347 | source = "registry+https://github.com/rust-lang/crates.io-index"
1348 | checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c"
1349 |
1350 | [[package]]
1351 | name = "plotters"
1352 | version = "0.3.7"
1353 | source = "registry+https://github.com/rust-lang/crates.io-index"
1354 | checksum = "5aeb6f403d7a4911efb1e33402027fc44f29b5bf6def3effcc22d7bb75f2b747"
1355 | dependencies = [
1356 | "num-traits",
1357 | "plotters-backend",
1358 | "plotters-svg",
1359 | "wasm-bindgen",
1360 | "web-sys",
1361 | ]
1362 |
1363 | [[package]]
1364 | name = "plotters-backend"
1365 | version = "0.3.7"
1366 | source = "registry+https://github.com/rust-lang/crates.io-index"
1367 | checksum = "df42e13c12958a16b3f7f4386b9ab1f3e7933914ecea48da7139435263a4172a"
1368 |
1369 | [[package]]
1370 | name = "plotters-svg"
1371 | version = "0.3.7"
1372 | source = "registry+https://github.com/rust-lang/crates.io-index"
1373 | checksum = "51bae2ac328883f7acdfea3d66a7c35751187f870bc81f94563733a154d7a670"
1374 | dependencies = [
1375 | "plotters-backend",
1376 | ]
1377 |
1378 | [[package]]
1379 | name = "potential_utf"
1380 | version = "0.1.2"
1381 | source = "registry+https://github.com/rust-lang/crates.io-index"
1382 | checksum = "e5a7c30837279ca13e7c867e9e40053bc68740f988cb07f7ca6df43cc734b585"
1383 | dependencies = [
1384 | "zerovec",
1385 | ]
1386 |
1387 | [[package]]
1388 | name = "powerfmt"
1389 | version = "0.2.0"
1390 | source = "registry+https://github.com/rust-lang/crates.io-index"
1391 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391"
1392 |
1393 | [[package]]
1394 | name = "ppv-lite86"
1395 | version = "0.2.21"
1396 | source = "registry+https://github.com/rust-lang/crates.io-index"
1397 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9"
1398 | dependencies = [
1399 | "zerocopy",
1400 | ]
1401 |
1402 | [[package]]
1403 | name = "proc-macro-crate"
1404 | version = "3.3.0"
1405 | source = "registry+https://github.com/rust-lang/crates.io-index"
1406 | checksum = "edce586971a4dfaa28950c6f18ed55e0406c1ab88bbce2c6f6293a7aaba73d35"
1407 | dependencies = [
1408 | "toml_edit",
1409 | ]
1410 |
1411 | [[package]]
1412 | name = "proc-macro-error-attr2"
1413 | version = "2.0.0"
1414 | source = "registry+https://github.com/rust-lang/crates.io-index"
1415 | checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
1416 | dependencies = [
1417 | "proc-macro2",
1418 | "quote",
1419 | ]
1420 |
1421 | [[package]]
1422 | name = "proc-macro-error2"
1423 | version = "2.0.1"
1424 | source = "registry+https://github.com/rust-lang/crates.io-index"
1425 | checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
1426 | dependencies = [
1427 | "proc-macro-error-attr2",
1428 | "proc-macro2",
1429 | "quote",
1430 | "syn 2.0.106",
1431 | ]
1432 |
1433 | [[package]]
1434 | name = "proc-macro2"
1435 | version = "1.0.101"
1436 | source = "registry+https://github.com/rust-lang/crates.io-index"
1437 | checksum = "89ae43fd86e4158d6db51ad8e2b80f313af9cc74f5c0e03ccb87de09998732de"
1438 | dependencies = [
1439 | "unicode-ident",
1440 | ]
1441 |
1442 | [[package]]
1443 | name = "proc-macro2-diagnostics"
1444 | version = "0.10.1"
1445 | source = "registry+https://github.com/rust-lang/crates.io-index"
1446 | checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8"
1447 | dependencies = [
1448 | "proc-macro2",
1449 | "quote",
1450 | "syn 2.0.106",
1451 | "version_check",
1452 | "yansi",
1453 | ]
1454 |
1455 | [[package]]
1456 | name = "ptr_meta"
1457 | version = "0.1.4"
1458 | source = "registry+https://github.com/rust-lang/crates.io-index"
1459 | checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1"
1460 | dependencies = [
1461 | "ptr_meta_derive 0.1.4",
1462 | ]
1463 |
1464 | [[package]]
1465 | name = "ptr_meta"
1466 | version = "0.3.0"
1467 | source = "registry+https://github.com/rust-lang/crates.io-index"
1468 | checksum = "fe9e76f66d3f9606f44e45598d155cb13ecf09f4a28199e48daf8c8fc937ea90"
1469 | dependencies = [
1470 | "ptr_meta_derive 0.3.0",
1471 | ]
1472 |
1473 | [[package]]
1474 | name = "ptr_meta_derive"
1475 | version = "0.1.4"
1476 | source = "registry+https://github.com/rust-lang/crates.io-index"
1477 | checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac"
1478 | dependencies = [
1479 | "proc-macro2",
1480 | "quote",
1481 | "syn 1.0.109",
1482 | ]
1483 |
1484 | [[package]]
1485 | name = "ptr_meta_derive"
1486 | version = "0.3.0"
1487 | source = "registry+https://github.com/rust-lang/crates.io-index"
1488 | checksum = "ca414edb151b4c8d125c12566ab0d74dc9cdba36fb80eb7b848c15f495fd32d1"
1489 | dependencies = [
1490 | "proc-macro2",
1491 | "quote",
1492 | "syn 2.0.106",
1493 | ]
1494 |
1495 | [[package]]
1496 | name = "quote"
1497 | version = "1.0.40"
1498 | source = "registry+https://github.com/rust-lang/crates.io-index"
1499 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d"
1500 | dependencies = [
1501 | "proc-macro2",
1502 | ]
1503 |
1504 | [[package]]
1505 | name = "radium"
1506 | version = "0.7.0"
1507 | source = "registry+https://github.com/rust-lang/crates.io-index"
1508 | checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
1509 |
1510 | [[package]]
1511 | name = "rancor"
1512 | version = "0.1.0"
1513 | source = "registry+https://github.com/rust-lang/crates.io-index"
1514 | checksum = "caf5f7161924b9d1cea0e4cabc97c372cea92b5f927fc13c6bca67157a0ad947"
1515 | dependencies = [
1516 | "ptr_meta 0.3.0",
1517 | ]
1518 |
1519 | [[package]]
1520 | name = "rand"
1521 | version = "0.8.5"
1522 | source = "registry+https://github.com/rust-lang/crates.io-index"
1523 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
1524 | dependencies = [
1525 | "libc",
1526 | "rand_chacha",
1527 | "rand_core",
1528 | ]
1529 |
1530 | [[package]]
1531 | name = "rand_chacha"
1532 | version = "0.3.1"
1533 | source = "registry+https://github.com/rust-lang/crates.io-index"
1534 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
1535 | dependencies = [
1536 | "ppv-lite86",
1537 | "rand_core",
1538 | ]
1539 |
1540 | [[package]]
1541 | name = "rand_core"
1542 | version = "0.6.4"
1543 | source = "registry+https://github.com/rust-lang/crates.io-index"
1544 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
1545 | dependencies = [
1546 | "getrandom",
1547 | ]
1548 |
1549 | [[package]]
1550 | name = "rayon"
1551 | version = "1.11.0"
1552 | source = "registry+https://github.com/rust-lang/crates.io-index"
1553 | checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
1554 | dependencies = [
1555 | "either",
1556 | "rayon-core",
1557 | ]
1558 |
1559 | [[package]]
1560 | name = "rayon-core"
1561 | version = "1.13.0"
1562 | source = "registry+https://github.com/rust-lang/crates.io-index"
1563 | checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
1564 | dependencies = [
1565 | "crossbeam-deque",
1566 | "crossbeam-utils",
1567 | ]
1568 |
1569 | [[package]]
1570 | name = "redis"
1571 | version = "1.0.0"
1572 | source = "registry+https://github.com/rust-lang/crates.io-index"
1573 | checksum = "47ba378d39b8053bffbfc2750220f5a24a06189b5129523d5db01618774e0239"
1574 | dependencies = [
1575 | "arcstr",
1576 | "combine",
1577 | "itoa",
1578 | "num-bigint",
1579 | "percent-encoding",
1580 | "ryu",
1581 | "socket2",
1582 | "url",
1583 | "xxhash-rust",
1584 | ]
1585 |
1586 | [[package]]
1587 | name = "redox_syscall"
1588 | version = "0.5.17"
1589 | source = "registry+https://github.com/rust-lang/crates.io-index"
1590 | checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
1591 | dependencies = [
1592 | "bitflags",
1593 | ]
1594 |
1595 | [[package]]
1596 | name = "regex"
1597 | version = "1.11.2"
1598 | source = "registry+https://github.com/rust-lang/crates.io-index"
1599 | checksum = "23d7fd106d8c02486a8d64e778353d1cffe08ce79ac2e82f540c86d0facf6912"
1600 | dependencies = [
1601 | "aho-corasick",
1602 | "memchr",
1603 | "regex-automata",
1604 | "regex-syntax",
1605 | ]
1606 |
1607 | [[package]]
1608 | name = "regex-automata"
1609 | version = "0.4.10"
1610 | source = "registry+https://github.com/rust-lang/crates.io-index"
1611 | checksum = "6b9458fa0bfeeac22b5ca447c63aaf45f28439a709ccd244698632f9aa6394d6"
1612 | dependencies = [
1613 | "aho-corasick",
1614 | "memchr",
1615 | "regex-syntax",
1616 | ]
1617 |
1618 | [[package]]
1619 | name = "regex-syntax"
1620 | version = "0.8.6"
1621 | source = "registry+https://github.com/rust-lang/crates.io-index"
1622 | checksum = "caf4aa5b0f434c91fe5c7f1ecb6a5ece2130b02ad2a590589dda5146df959001"
1623 |
1624 | [[package]]
1625 | name = "rend"
1626 | version = "0.4.2"
1627 | source = "registry+https://github.com/rust-lang/crates.io-index"
1628 | checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c"
1629 | dependencies = [
1630 | "bytecheck",
1631 | ]
1632 |
1633 | [[package]]
1634 | name = "rend"
1635 | version = "0.5.2"
1636 | source = "registry+https://github.com/rust-lang/crates.io-index"
1637 | checksum = "a35e8a6bf28cd121053a66aa2e6a2e3eaffad4a60012179f0e864aa5ffeff215"
1638 |
1639 | [[package]]
1640 | name = "rkyv"
1641 | version = "0.7.45"
1642 | source = "registry+https://github.com/rust-lang/crates.io-index"
1643 | checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b"
1644 | dependencies = [
1645 | "bitvec",
1646 | "bytecheck",
1647 | "bytes",
1648 | "hashbrown 0.12.3",
1649 | "ptr_meta 0.1.4",
1650 | "rend 0.4.2",
1651 | "rkyv_derive 0.7.45",
1652 | "seahash",
1653 | "tinyvec",
1654 | "uuid",
1655 | ]
1656 |
1657 | [[package]]
1658 | name = "rkyv"
1659 | version = "0.8.11"
1660 | source = "registry+https://github.com/rust-lang/crates.io-index"
1661 | checksum = "19f5c3e5da784cd8c69d32cdc84673f3204536ca56e1fa01be31a74b92c932ac"
1662 | dependencies = [
1663 | "bytes",
1664 | "hashbrown 0.15.5",
1665 | "indexmap",
1666 | "munge",
1667 | "ptr_meta 0.3.0",
1668 | "rancor",
1669 | "rend 0.5.2",
1670 | "rkyv_derive 0.8.11",
1671 | "tinyvec",
1672 | "uuid",
1673 | ]
1674 |
1675 | [[package]]
1676 | name = "rkyv_derive"
1677 | version = "0.7.45"
1678 | source = "registry+https://github.com/rust-lang/crates.io-index"
1679 | checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0"
1680 | dependencies = [
1681 | "proc-macro2",
1682 | "quote",
1683 | "syn 1.0.109",
1684 | ]
1685 |
1686 | [[package]]
1687 | name = "rkyv_derive"
1688 | version = "0.8.11"
1689 | source = "registry+https://github.com/rust-lang/crates.io-index"
1690 | checksum = "4270433626cffc9c4c1d3707dd681f2a2718d3d7b09ad754bec137acecda8d22"
1691 | dependencies = [
1692 | "proc-macro2",
1693 | "quote",
1694 | "syn 2.0.106",
1695 | ]
1696 |
1697 | [[package]]
1698 | name = "rsa"
1699 | version = "0.9.8"
1700 | source = "registry+https://github.com/rust-lang/crates.io-index"
1701 | checksum = "78928ac1ed176a5ca1d17e578a1825f3d81ca54cf41053a592584b020cfd691b"
1702 | dependencies = [
1703 | "const-oid",
1704 | "digest",
1705 | "num-bigint-dig",
1706 | "num-integer",
1707 | "num-traits",
1708 | "pkcs1",
1709 | "pkcs8",
1710 | "rand_core",
1711 | "signature",
1712 | "spki",
1713 | "subtle",
1714 | "zeroize",
1715 | ]
1716 |
1717 | [[package]]
1718 | name = "rust_decimal"
1719 | version = "1.37.2"
1720 | source = "registry+https://github.com/rust-lang/crates.io-index"
1721 | checksum = "b203a6425500a03e0919c42d3c47caca51e79f1132046626d2c8871c5092035d"
1722 | dependencies = [
1723 | "arrayvec",
1724 | "borsh",
1725 | "bytes",
1726 | "num-traits",
1727 | "rand",
1728 | "rkyv 0.7.45",
1729 | "serde",
1730 | "serde_json",
1731 | ]
1732 |
1733 | [[package]]
1734 | name = "rustc-demangle"
1735 | version = "0.1.26"
1736 | source = "registry+https://github.com/rust-lang/crates.io-index"
1737 | checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
1738 |
1739 | [[package]]
1740 | name = "rustversion"
1741 | version = "1.0.22"
1742 | source = "registry+https://github.com/rust-lang/crates.io-index"
1743 | checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
1744 |
1745 | [[package]]
1746 | name = "ryu"
1747 | version = "1.0.20"
1748 | source = "registry+https://github.com/rust-lang/crates.io-index"
1749 | checksum = "28d3b2b1366ec20994f1fd18c3c594f05c5dd4bc44d8bb0c1c632c8d6829481f"
1750 |
1751 | [[package]]
1752 | name = "same-file"
1753 | version = "1.0.6"
1754 | source = "registry+https://github.com/rust-lang/crates.io-index"
1755 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
1756 | dependencies = [
1757 | "winapi-util",
1758 | ]
1759 |
1760 | [[package]]
1761 | name = "scopeguard"
1762 | version = "1.2.0"
1763 | source = "registry+https://github.com/rust-lang/crates.io-index"
1764 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
1765 |
1766 | [[package]]
1767 | name = "sea-bae"
1768 | version = "0.2.1"
1769 | source = "registry+https://github.com/rust-lang/crates.io-index"
1770 | checksum = "f694a6ab48f14bc063cfadff30ab551d3c7e46d8f81836c51989d548f44a2a25"
1771 | dependencies = [
1772 | "heck 0.4.1",
1773 | "proc-macro-error2",
1774 | "proc-macro2",
1775 | "quote",
1776 | "syn 2.0.106",
1777 | ]
1778 |
1779 | [[package]]
1780 | name = "sea-orm"
1781 | version = "1.1.14"
1782 | source = "registry+https://github.com/rust-lang/crates.io-index"
1783 | checksum = "34963b2d68331ef5fbc8aa28a53781471c15f90ba1ad4f2689d21ce8b9a9d1f1"
1784 | dependencies = [
1785 | "async-stream",
1786 | "async-trait",
1787 | "bigdecimal",
1788 | "chrono",
1789 | "futures-util",
1790 | "log",
1791 | "ouroboros",
1792 | "pgvector",
1793 | "rust_decimal",
1794 | "sea-orm-macros",
1795 | "sea-query",
1796 | "sea-query-binder",
1797 | "serde",
1798 | "serde_json",
1799 | "sqlx",
1800 | "strum",
1801 | "thiserror",
1802 | "time",
1803 | "tracing",
1804 | "url",
1805 | "uuid",
1806 | ]
1807 |
1808 | [[package]]
1809 | name = "sea-orm-macros"
1810 | version = "1.1.14"
1811 | source = "registry+https://github.com/rust-lang/crates.io-index"
1812 | checksum = "a489127c872766445b4e28f846825f89a076ac3af2591d1365503a68f93e974c"
1813 | dependencies = [
1814 | "heck 0.5.0",
1815 | "proc-macro2",
1816 | "quote",
1817 | "sea-bae",
1818 | "syn 2.0.106",
1819 | "unicode-ident",
1820 | ]
1821 |
1822 | [[package]]
1823 | name = "sea-query"
1824 | version = "0.32.7"
1825 | source = "registry+https://github.com/rust-lang/crates.io-index"
1826 | checksum = "8a5d1c518eaf5eda38e5773f902b26ab6d5e9e9e2bb2349ca6c64cf96f80448c"
1827 | dependencies = [
1828 | "bigdecimal",
1829 | "chrono",
1830 | "inherent",
1831 | "ordered-float",
1832 | "rust_decimal",
1833 | "serde_json",
1834 | "time",
1835 | "uuid",
1836 | ]
1837 |
1838 | [[package]]
1839 | name = "sea-query-binder"
1840 | version = "0.7.0"
1841 | source = "registry+https://github.com/rust-lang/crates.io-index"
1842 | checksum = "b0019f47430f7995af63deda77e238c17323359af241233ec768aba1faea7608"
1843 | dependencies = [
1844 | "bigdecimal",
1845 | "chrono",
1846 | "rust_decimal",
1847 | "sea-query",
1848 | "serde_json",
1849 | "sqlx",
1850 | "time",
1851 | "uuid",
1852 | ]
1853 |
1854 | [[package]]
1855 | name = "seahash"
1856 | version = "4.1.0"
1857 | source = "registry+https://github.com/rust-lang/crates.io-index"
1858 | checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b"
1859 |
1860 | [[package]]
1861 | name = "serde"
1862 | version = "1.0.219"
1863 | source = "registry+https://github.com/rust-lang/crates.io-index"
1864 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6"
1865 | dependencies = [
1866 | "serde_derive",
1867 | ]
1868 |
1869 | [[package]]
1870 | name = "serde_derive"
1871 | version = "1.0.219"
1872 | source = "registry+https://github.com/rust-lang/crates.io-index"
1873 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00"
1874 | dependencies = [
1875 | "proc-macro2",
1876 | "quote",
1877 | "syn 2.0.106",
1878 | ]
1879 |
1880 | [[package]]
1881 | name = "serde_json"
1882 | version = "1.0.143"
1883 | source = "registry+https://github.com/rust-lang/crates.io-index"
1884 | checksum = "d401abef1d108fbd9cbaebc3e46611f4b1021f714a0597a71f41ee463f5f4a5a"
1885 | dependencies = [
1886 | "itoa",
1887 | "memchr",
1888 | "ryu",
1889 | "serde",
1890 | ]
1891 |
1892 | [[package]]
1893 | name = "serde_urlencoded"
1894 | version = "0.7.1"
1895 | source = "registry+https://github.com/rust-lang/crates.io-index"
1896 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd"
1897 | dependencies = [
1898 | "form_urlencoded",
1899 | "itoa",
1900 | "ryu",
1901 | "serde",
1902 | ]
1903 |
1904 | [[package]]
1905 | name = "sha1"
1906 | version = "0.10.6"
1907 | source = "registry+https://github.com/rust-lang/crates.io-index"
1908 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba"
1909 | dependencies = [
1910 | "cfg-if",
1911 | "cpufeatures",
1912 | "digest",
1913 | ]
1914 |
1915 | [[package]]
1916 | name = "sha2"
1917 | version = "0.10.9"
1918 | source = "registry+https://github.com/rust-lang/crates.io-index"
1919 | checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
1920 | dependencies = [
1921 | "cfg-if",
1922 | "cpufeatures",
1923 | "digest",
1924 | ]
1925 |
1926 | [[package]]
1927 | name = "shlex"
1928 | version = "1.3.0"
1929 | source = "registry+https://github.com/rust-lang/crates.io-index"
1930 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
1931 |
1932 | [[package]]
1933 | name = "signature"
1934 | version = "2.2.0"
1935 | source = "registry+https://github.com/rust-lang/crates.io-index"
1936 | checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de"
1937 | dependencies = [
1938 | "digest",
1939 | "rand_core",
1940 | ]
1941 |
1942 | [[package]]
1943 | name = "simdutf8"
1944 | version = "0.1.5"
1945 | source = "registry+https://github.com/rust-lang/crates.io-index"
1946 | checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e"
1947 |
1948 | [[package]]
1949 | name = "slab"
1950 | version = "0.4.11"
1951 | source = "registry+https://github.com/rust-lang/crates.io-index"
1952 | checksum = "7a2ae44ef20feb57a68b23d846850f861394c2e02dc425a50098ae8c90267589"
1953 |
1954 | [[package]]
1955 | name = "smallvec"
1956 | version = "1.15.1"
1957 | source = "registry+https://github.com/rust-lang/crates.io-index"
1958 | checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03"
1959 | dependencies = [
1960 | "serde",
1961 | ]
1962 |
1963 | [[package]]
1964 | name = "socket2"
1965 | version = "0.6.0"
1966 | source = "registry+https://github.com/rust-lang/crates.io-index"
1967 | checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
1968 | dependencies = [
1969 | "libc",
1970 | "windows-sys 0.59.0",
1971 | ]
1972 |
1973 | [[package]]
1974 | name = "spin"
1975 | version = "0.9.8"
1976 | source = "registry+https://github.com/rust-lang/crates.io-index"
1977 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
1978 | dependencies = [
1979 | "lock_api",
1980 | ]
1981 |
1982 | [[package]]
1983 | name = "spki"
1984 | version = "0.7.3"
1985 | source = "registry+https://github.com/rust-lang/crates.io-index"
1986 | checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d"
1987 | dependencies = [
1988 | "base64ct",
1989 | "der",
1990 | ]
1991 |
1992 | [[package]]
1993 | name = "sqlx"
1994 | version = "0.8.6"
1995 | source = "registry+https://github.com/rust-lang/crates.io-index"
1996 | checksum = "1fefb893899429669dcdd979aff487bd78f4064e5e7907e4269081e0ef7d97dc"
1997 | dependencies = [
1998 | "sqlx-core",
1999 | "sqlx-macros",
2000 | "sqlx-mysql",
2001 | "sqlx-postgres",
2002 | "sqlx-sqlite",
2003 | ]
2004 |
2005 | [[package]]
2006 | name = "sqlx-core"
2007 | version = "0.8.6"
2008 | source = "registry+https://github.com/rust-lang/crates.io-index"
2009 | checksum = "ee6798b1838b6a0f69c007c133b8df5866302197e404e8b6ee8ed3e3a5e68dc6"
2010 | dependencies = [
2011 | "base64",
2012 | "bigdecimal",
2013 | "bytes",
2014 | "chrono",
2015 | "crc",
2016 | "crossbeam-queue",
2017 | "either",
2018 | "event-listener",
2019 | "futures-core",
2020 | "futures-intrusive",
2021 | "futures-io",
2022 | "futures-util",
2023 | "hashbrown 0.15.5",
2024 | "hashlink",
2025 | "indexmap",
2026 | "log",
2027 | "memchr",
2028 | "once_cell",
2029 | "percent-encoding",
2030 | "rust_decimal",
2031 | "serde",
2032 | "serde_json",
2033 | "sha2",
2034 | "smallvec",
2035 | "thiserror",
2036 | "time",
2037 | "tracing",
2038 | "url",
2039 | "uuid",
2040 | ]
2041 |
2042 | [[package]]
2043 | name = "sqlx-macros"
2044 | version = "0.8.6"
2045 | source = "registry+https://github.com/rust-lang/crates.io-index"
2046 | checksum = "a2d452988ccaacfbf5e0bdbc348fb91d7c8af5bee192173ac3636b5fb6e6715d"
2047 | dependencies = [
2048 | "proc-macro2",
2049 | "quote",
2050 | "sqlx-core",
2051 | "sqlx-macros-core",
2052 | "syn 2.0.106",
2053 | ]
2054 |
2055 | [[package]]
2056 | name = "sqlx-macros-core"
2057 | version = "0.8.6"
2058 | source = "registry+https://github.com/rust-lang/crates.io-index"
2059 | checksum = "19a9c1841124ac5a61741f96e1d9e2ec77424bf323962dd894bdb93f37d5219b"
2060 | dependencies = [
2061 | "dotenvy",
2062 | "either",
2063 | "heck 0.5.0",
2064 | "hex",
2065 | "once_cell",
2066 | "proc-macro2",
2067 | "quote",
2068 | "serde",
2069 | "serde_json",
2070 | "sha2",
2071 | "sqlx-core",
2072 | "sqlx-mysql",
2073 | "sqlx-postgres",
2074 | "sqlx-sqlite",
2075 | "syn 2.0.106",
2076 | "url",
2077 | ]
2078 |
2079 | [[package]]
2080 | name = "sqlx-mysql"
2081 | version = "0.8.6"
2082 | source = "registry+https://github.com/rust-lang/crates.io-index"
2083 | checksum = "aa003f0038df784eb8fecbbac13affe3da23b45194bd57dba231c8f48199c526"
2084 | dependencies = [
2085 | "atoi",
2086 | "base64",
2087 | "bigdecimal",
2088 | "bitflags",
2089 | "byteorder",
2090 | "bytes",
2091 | "chrono",
2092 | "crc",
2093 | "digest",
2094 | "dotenvy",
2095 | "either",
2096 | "futures-channel",
2097 | "futures-core",
2098 | "futures-io",
2099 | "futures-util",
2100 | "generic-array",
2101 | "hex",
2102 | "hkdf",
2103 | "hmac",
2104 | "itoa",
2105 | "log",
2106 | "md-5",
2107 | "memchr",
2108 | "once_cell",
2109 | "percent-encoding",
2110 | "rand",
2111 | "rsa",
2112 | "rust_decimal",
2113 | "serde",
2114 | "sha1",
2115 | "sha2",
2116 | "smallvec",
2117 | "sqlx-core",
2118 | "stringprep",
2119 | "thiserror",
2120 | "time",
2121 | "tracing",
2122 | "uuid",
2123 | "whoami",
2124 | ]
2125 |
2126 | [[package]]
2127 | name = "sqlx-postgres"
2128 | version = "0.8.6"
2129 | source = "registry+https://github.com/rust-lang/crates.io-index"
2130 | checksum = "db58fcd5a53cf07c184b154801ff91347e4c30d17a3562a635ff028ad5deda46"
2131 | dependencies = [
2132 | "atoi",
2133 | "base64",
2134 | "bigdecimal",
2135 | "bitflags",
2136 | "byteorder",
2137 | "chrono",
2138 | "crc",
2139 | "dotenvy",
2140 | "etcetera",
2141 | "futures-channel",
2142 | "futures-core",
2143 | "futures-util",
2144 | "hex",
2145 | "hkdf",
2146 | "hmac",
2147 | "home",
2148 | "itoa",
2149 | "log",
2150 | "md-5",
2151 | "memchr",
2152 | "num-bigint",
2153 | "once_cell",
2154 | "rand",
2155 | "rust_decimal",
2156 | "serde",
2157 | "serde_json",
2158 | "sha2",
2159 | "smallvec",
2160 | "sqlx-core",
2161 | "stringprep",
2162 | "thiserror",
2163 | "time",
2164 | "tracing",
2165 | "uuid",
2166 | "whoami",
2167 | ]
2168 |
2169 | [[package]]
2170 | name = "sqlx-sqlite"
2171 | version = "0.8.6"
2172 | source = "registry+https://github.com/rust-lang/crates.io-index"
2173 | checksum = "c2d12fe70b2c1b4401038055f90f151b78208de1f9f89a7dbfd41587a10c3eea"
2174 | dependencies = [
2175 | "atoi",
2176 | "chrono",
2177 | "flume",
2178 | "futures-channel",
2179 | "futures-core",
2180 | "futures-executor",
2181 | "futures-intrusive",
2182 | "futures-util",
2183 | "libsqlite3-sys",
2184 | "log",
2185 | "percent-encoding",
2186 | "serde",
2187 | "serde_urlencoded",
2188 | "sqlx-core",
2189 | "thiserror",
2190 | "time",
2191 | "tracing",
2192 | "url",
2193 | "uuid",
2194 | ]
2195 |
2196 | [[package]]
2197 | name = "stable_deref_trait"
2198 | version = "1.2.0"
2199 | source = "registry+https://github.com/rust-lang/crates.io-index"
2200 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
2201 |
2202 | [[package]]
2203 | name = "static_assertions"
2204 | version = "1.1.0"
2205 | source = "registry+https://github.com/rust-lang/crates.io-index"
2206 | checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
2207 |
2208 | [[package]]
2209 | name = "stringprep"
2210 | version = "0.1.5"
2211 | source = "registry+https://github.com/rust-lang/crates.io-index"
2212 | checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1"
2213 | dependencies = [
2214 | "unicode-bidi",
2215 | "unicode-normalization",
2216 | "unicode-properties",
2217 | ]
2218 |
2219 | [[package]]
2220 | name = "strum"
2221 | version = "0.26.3"
2222 | source = "registry+https://github.com/rust-lang/crates.io-index"
2223 | checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06"
2224 |
2225 | [[package]]
2226 | name = "subtle"
2227 | version = "2.6.1"
2228 | source = "registry+https://github.com/rust-lang/crates.io-index"
2229 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
2230 |
2231 | [[package]]
2232 | name = "syn"
2233 | version = "1.0.109"
2234 | source = "registry+https://github.com/rust-lang/crates.io-index"
2235 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
2236 | dependencies = [
2237 | "proc-macro2",
2238 | "quote",
2239 | "unicode-ident",
2240 | ]
2241 |
2242 | [[package]]
2243 | name = "syn"
2244 | version = "2.0.106"
2245 | source = "registry+https://github.com/rust-lang/crates.io-index"
2246 | checksum = "ede7c438028d4436d71104916910f5bb611972c5cfd7f89b8300a8186e6fada6"
2247 | dependencies = [
2248 | "proc-macro2",
2249 | "quote",
2250 | "unicode-ident",
2251 | ]
2252 |
2253 | [[package]]
2254 | name = "synstructure"
2255 | version = "0.13.2"
2256 | source = "registry+https://github.com/rust-lang/crates.io-index"
2257 | checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2"
2258 | dependencies = [
2259 | "proc-macro2",
2260 | "quote",
2261 | "syn 2.0.106",
2262 | ]
2263 |
2264 | [[package]]
2265 | name = "tap"
2266 | version = "1.0.1"
2267 | source = "registry+https://github.com/rust-lang/crates.io-index"
2268 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
2269 |
2270 | [[package]]
2271 | name = "thiserror"
2272 | version = "2.0.16"
2273 | source = "registry+https://github.com/rust-lang/crates.io-index"
2274 | checksum = "3467d614147380f2e4e374161426ff399c91084acd2363eaf549172b3d5e60c0"
2275 | dependencies = [
2276 | "thiserror-impl",
2277 | ]
2278 |
2279 | [[package]]
2280 | name = "thiserror-impl"
2281 | version = "2.0.16"
2282 | source = "registry+https://github.com/rust-lang/crates.io-index"
2283 | checksum = "6c5e1be1c48b9172ee610da68fd9cd2770e7a4056cb3fc98710ee6906f0c7960"
2284 | dependencies = [
2285 | "proc-macro2",
2286 | "quote",
2287 | "syn 2.0.106",
2288 | ]
2289 |
2290 | [[package]]
2291 | name = "time"
2292 | version = "0.3.41"
2293 | source = "registry+https://github.com/rust-lang/crates.io-index"
2294 | checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40"
2295 | dependencies = [
2296 | "deranged",
2297 | "itoa",
2298 | "num-conv",
2299 | "powerfmt",
2300 | "serde",
2301 | "time-core",
2302 | "time-macros",
2303 | ]
2304 |
2305 | [[package]]
2306 | name = "time-core"
2307 | version = "0.1.4"
2308 | source = "registry+https://github.com/rust-lang/crates.io-index"
2309 | checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c"
2310 |
2311 | [[package]]
2312 | name = "time-macros"
2313 | version = "0.2.22"
2314 | source = "registry+https://github.com/rust-lang/crates.io-index"
2315 | checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49"
2316 | dependencies = [
2317 | "num-conv",
2318 | "time-core",
2319 | ]
2320 |
2321 | [[package]]
2322 | name = "tinystr"
2323 | version = "0.8.1"
2324 | source = "registry+https://github.com/rust-lang/crates.io-index"
2325 | checksum = "5d4f6d1145dcb577acf783d4e601bc1d76a13337bb54e6233add580b07344c8b"
2326 | dependencies = [
2327 | "displaydoc",
2328 | "zerovec",
2329 | ]
2330 |
2331 | [[package]]
2332 | name = "tinytemplate"
2333 | version = "1.2.1"
2334 | source = "registry+https://github.com/rust-lang/crates.io-index"
2335 | checksum = "be4d6b5f19ff7664e8c98d03e2139cb510db9b0a60b55f8e8709b689d939b6bc"
2336 | dependencies = [
2337 | "serde",
2338 | "serde_json",
2339 | ]
2340 |
2341 | [[package]]
2342 | name = "tinyvec"
2343 | version = "1.10.0"
2344 | source = "registry+https://github.com/rust-lang/crates.io-index"
2345 | checksum = "bfa5fdc3bce6191a1dbc8c02d5c8bffcf557bafa17c124c5264a458f1b0613fa"
2346 | dependencies = [
2347 | "tinyvec_macros",
2348 | ]
2349 |
2350 | [[package]]
2351 | name = "tinyvec_macros"
2352 | version = "0.1.1"
2353 | source = "registry+https://github.com/rust-lang/crates.io-index"
2354 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
2355 |
2356 | [[package]]
2357 | name = "tokio"
2358 | version = "1.47.1"
2359 | source = "registry+https://github.com/rust-lang/crates.io-index"
2360 | checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
2361 | dependencies = [
2362 | "backtrace",
2363 | "io-uring",
2364 | "libc",
2365 | "mio",
2366 | "pin-project-lite",
2367 | "slab",
2368 | "tokio-macros",
2369 | ]
2370 |
2371 | [[package]]
2372 | name = "tokio-macros"
2373 | version = "2.5.0"
2374 | source = "registry+https://github.com/rust-lang/crates.io-index"
2375 | checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8"
2376 | dependencies = [
2377 | "proc-macro2",
2378 | "quote",
2379 | "syn 2.0.106",
2380 | ]
2381 |
2382 | [[package]]
2383 | name = "toml_datetime"
2384 | version = "0.6.11"
2385 | source = "registry+https://github.com/rust-lang/crates.io-index"
2386 | checksum = "22cddaf88f4fbc13c51aebbf5f8eceb5c7c5a9da2ac40a13519eb5b0a0e8f11c"
2387 |
2388 | [[package]]
2389 | name = "toml_edit"
2390 | version = "0.22.27"
2391 | source = "registry+https://github.com/rust-lang/crates.io-index"
2392 | checksum = "41fe8c660ae4257887cf66394862d21dbca4a6ddd26f04a3560410406a2f819a"
2393 | dependencies = [
2394 | "indexmap",
2395 | "toml_datetime",
2396 | "winnow",
2397 | ]
2398 |
2399 | [[package]]
2400 | name = "tracing"
2401 | version = "0.1.41"
2402 | source = "registry+https://github.com/rust-lang/crates.io-index"
2403 | checksum = "784e0ac535deb450455cbfa28a6f0df145ea1bb7ae51b821cf5e7927fdcfbdd0"
2404 | dependencies = [
2405 | "log",
2406 | "pin-project-lite",
2407 | "tracing-attributes",
2408 | "tracing-core",
2409 | ]
2410 |
2411 | [[package]]
2412 | name = "tracing-attributes"
2413 | version = "0.1.30"
2414 | source = "registry+https://github.com/rust-lang/crates.io-index"
2415 | checksum = "81383ab64e72a7a8b8e13130c49e3dab29def6d0c7d76a03087b3cf71c5c6903"
2416 | dependencies = [
2417 | "proc-macro2",
2418 | "quote",
2419 | "syn 2.0.106",
2420 | ]
2421 |
2422 | [[package]]
2423 | name = "tracing-core"
2424 | version = "0.1.34"
2425 | source = "registry+https://github.com/rust-lang/crates.io-index"
2426 | checksum = "b9d12581f227e93f094d3af2ae690a574abb8a2b9b7a96e7cfe9647b2b617678"
2427 | dependencies = [
2428 | "once_cell",
2429 | ]
2430 |
2431 | [[package]]
2432 | name = "ts-rs"
2433 | version = "11.0.1"
2434 | source = "registry+https://github.com/rust-lang/crates.io-index"
2435 | checksum = "6ef1b7a6d914a34127ed8e1fa927eb7088903787bcded4fa3eef8f85ee1568be"
2436 | dependencies = [
2437 | "thiserror",
2438 | "ts-rs-macros",
2439 | ]
2440 |
2441 | [[package]]
2442 | name = "ts-rs-macros"
2443 | version = "11.0.1"
2444 | source = "registry+https://github.com/rust-lang/crates.io-index"
2445 | checksum = "e9d4ed7b4c18cc150a6a0a1e9ea1ecfa688791220781af6e119f9599a8502a0a"
2446 | dependencies = [
2447 | "proc-macro2",
2448 | "quote",
2449 | "syn 2.0.106",
2450 | ]
2451 |
2452 | [[package]]
2453 | name = "typenum"
2454 | version = "1.18.0"
2455 | source = "registry+https://github.com/rust-lang/crates.io-index"
2456 | checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f"
2457 |
2458 | [[package]]
2459 | name = "unicode-bidi"
2460 | version = "0.3.18"
2461 | source = "registry+https://github.com/rust-lang/crates.io-index"
2462 | checksum = "5c1cb5db39152898a79168971543b1cb5020dff7fe43c8dc468b0885f5e29df5"
2463 |
2464 | [[package]]
2465 | name = "unicode-ident"
2466 | version = "1.0.18"
2467 | source = "registry+https://github.com/rust-lang/crates.io-index"
2468 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512"
2469 |
2470 | [[package]]
2471 | name = "unicode-normalization"
2472 | version = "0.1.24"
2473 | source = "registry+https://github.com/rust-lang/crates.io-index"
2474 | checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956"
2475 | dependencies = [
2476 | "tinyvec",
2477 | ]
2478 |
2479 | [[package]]
2480 | name = "unicode-properties"
2481 | version = "0.1.3"
2482 | source = "registry+https://github.com/rust-lang/crates.io-index"
2483 | checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0"
2484 |
2485 | [[package]]
2486 | name = "url"
2487 | version = "2.5.7"
2488 | source = "registry+https://github.com/rust-lang/crates.io-index"
2489 | checksum = "08bc136a29a3d1758e07a9cca267be308aeebf5cfd5a10f3f67ab2097683ef5b"
2490 | dependencies = [
2491 | "form_urlencoded",
2492 | "idna",
2493 | "percent-encoding",
2494 | "serde",
2495 | ]
2496 |
2497 | [[package]]
2498 | name = "utf8_iter"
2499 | version = "1.0.4"
2500 | source = "registry+https://github.com/rust-lang/crates.io-index"
2501 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be"
2502 |
2503 | [[package]]
2504 | name = "uuid"
2505 | version = "1.18.0"
2506 | source = "registry+https://github.com/rust-lang/crates.io-index"
2507 | checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
2508 | dependencies = [
2509 | "js-sys",
2510 | "serde",
2511 | "wasm-bindgen",
2512 | ]
2513 |
2514 | [[package]]
2515 | name = "vcpkg"
2516 | version = "0.2.15"
2517 | source = "registry+https://github.com/rust-lang/crates.io-index"
2518 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426"
2519 |
2520 | [[package]]
2521 | name = "version_check"
2522 | version = "0.9.5"
2523 | source = "registry+https://github.com/rust-lang/crates.io-index"
2524 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a"
2525 |
2526 | [[package]]
2527 | name = "walkdir"
2528 | version = "2.5.0"
2529 | source = "registry+https://github.com/rust-lang/crates.io-index"
2530 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b"
2531 | dependencies = [
2532 | "same-file",
2533 | "winapi-util",
2534 | ]
2535 |
2536 | [[package]]
2537 | name = "wasi"
2538 | version = "0.11.1+wasi-snapshot-preview1"
2539 | source = "registry+https://github.com/rust-lang/crates.io-index"
2540 | checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b"
2541 |
2542 | [[package]]
2543 | name = "wasite"
2544 | version = "0.1.0"
2545 | source = "registry+https://github.com/rust-lang/crates.io-index"
2546 | checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b"
2547 |
2548 | [[package]]
2549 | name = "wasm-bindgen"
2550 | version = "0.2.100"
2551 | source = "registry+https://github.com/rust-lang/crates.io-index"
2552 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5"
2553 | dependencies = [
2554 | "cfg-if",
2555 | "once_cell",
2556 | "rustversion",
2557 | "wasm-bindgen-macro",
2558 | ]
2559 |
2560 | [[package]]
2561 | name = "wasm-bindgen-backend"
2562 | version = "0.2.100"
2563 | source = "registry+https://github.com/rust-lang/crates.io-index"
2564 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6"
2565 | dependencies = [
2566 | "bumpalo",
2567 | "log",
2568 | "proc-macro2",
2569 | "quote",
2570 | "syn 2.0.106",
2571 | "wasm-bindgen-shared",
2572 | ]
2573 |
2574 | [[package]]
2575 | name = "wasm-bindgen-macro"
2576 | version = "0.2.100"
2577 | source = "registry+https://github.com/rust-lang/crates.io-index"
2578 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407"
2579 | dependencies = [
2580 | "quote",
2581 | "wasm-bindgen-macro-support",
2582 | ]
2583 |
2584 | [[package]]
2585 | name = "wasm-bindgen-macro-support"
2586 | version = "0.2.100"
2587 | source = "registry+https://github.com/rust-lang/crates.io-index"
2588 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de"
2589 | dependencies = [
2590 | "proc-macro2",
2591 | "quote",
2592 | "syn 2.0.106",
2593 | "wasm-bindgen-backend",
2594 | "wasm-bindgen-shared",
2595 | ]
2596 |
2597 | [[package]]
2598 | name = "wasm-bindgen-shared"
2599 | version = "0.2.100"
2600 | source = "registry+https://github.com/rust-lang/crates.io-index"
2601 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d"
2602 | dependencies = [
2603 | "unicode-ident",
2604 | ]
2605 |
2606 | [[package]]
2607 | name = "web-sys"
2608 | version = "0.3.77"
2609 | source = "registry+https://github.com/rust-lang/crates.io-index"
2610 | checksum = "33b6dd2ef9186f1f2072e409e99cd22a975331a6b3591b12c764e0e55c60d5d2"
2611 | dependencies = [
2612 | "js-sys",
2613 | "wasm-bindgen",
2614 | ]
2615 |
2616 | [[package]]
2617 | name = "whoami"
2618 | version = "1.6.1"
2619 | source = "registry+https://github.com/rust-lang/crates.io-index"
2620 | checksum = "5d4a4db5077702ca3015d3d02d74974948aba2ad9e12ab7df718ee64ccd7e97d"
2621 | dependencies = [
2622 | "libredox",
2623 | "wasite",
2624 | ]
2625 |
2626 | [[package]]
2627 | name = "winapi-util"
2628 | version = "0.1.10"
2629 | source = "registry+https://github.com/rust-lang/crates.io-index"
2630 | checksum = "0978bf7171b3d90bac376700cb56d606feb40f251a475a5d6634613564460b22"
2631 | dependencies = [
2632 | "windows-sys 0.60.2",
2633 | ]
2634 |
2635 | [[package]]
2636 | name = "windows-core"
2637 | version = "0.61.2"
2638 | source = "registry+https://github.com/rust-lang/crates.io-index"
2639 | checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3"
2640 | dependencies = [
2641 | "windows-implement",
2642 | "windows-interface",
2643 | "windows-link",
2644 | "windows-result",
2645 | "windows-strings",
2646 | ]
2647 |
2648 | [[package]]
2649 | name = "windows-implement"
2650 | version = "0.60.0"
2651 | source = "registry+https://github.com/rust-lang/crates.io-index"
2652 | checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836"
2653 | dependencies = [
2654 | "proc-macro2",
2655 | "quote",
2656 | "syn 2.0.106",
2657 | ]
2658 |
2659 | [[package]]
2660 | name = "windows-interface"
2661 | version = "0.59.1"
2662 | source = "registry+https://github.com/rust-lang/crates.io-index"
2663 | checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8"
2664 | dependencies = [
2665 | "proc-macro2",
2666 | "quote",
2667 | "syn 2.0.106",
2668 | ]
2669 |
2670 | [[package]]
2671 | name = "windows-link"
2672 | version = "0.1.3"
2673 | source = "registry+https://github.com/rust-lang/crates.io-index"
2674 | checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a"
2675 |
2676 | [[package]]
2677 | name = "windows-result"
2678 | version = "0.3.4"
2679 | source = "registry+https://github.com/rust-lang/crates.io-index"
2680 | checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6"
2681 | dependencies = [
2682 | "windows-link",
2683 | ]
2684 |
2685 | [[package]]
2686 | name = "windows-strings"
2687 | version = "0.4.2"
2688 | source = "registry+https://github.com/rust-lang/crates.io-index"
2689 | checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57"
2690 | dependencies = [
2691 | "windows-link",
2692 | ]
2693 |
2694 | [[package]]
2695 | name = "windows-sys"
2696 | version = "0.48.0"
2697 | source = "registry+https://github.com/rust-lang/crates.io-index"
2698 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
2699 | dependencies = [
2700 | "windows-targets 0.48.5",
2701 | ]
2702 |
2703 | [[package]]
2704 | name = "windows-sys"
2705 | version = "0.59.0"
2706 | source = "registry+https://github.com/rust-lang/crates.io-index"
2707 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b"
2708 | dependencies = [
2709 | "windows-targets 0.52.6",
2710 | ]
2711 |
2712 | [[package]]
2713 | name = "windows-sys"
2714 | version = "0.60.2"
2715 | source = "registry+https://github.com/rust-lang/crates.io-index"
2716 | checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
2717 | dependencies = [
2718 | "windows-targets 0.53.3",
2719 | ]
2720 |
2721 | [[package]]
2722 | name = "windows-targets"
2723 | version = "0.48.5"
2724 | source = "registry+https://github.com/rust-lang/crates.io-index"
2725 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
2726 | dependencies = [
2727 | "windows_aarch64_gnullvm 0.48.5",
2728 | "windows_aarch64_msvc 0.48.5",
2729 | "windows_i686_gnu 0.48.5",
2730 | "windows_i686_msvc 0.48.5",
2731 | "windows_x86_64_gnu 0.48.5",
2732 | "windows_x86_64_gnullvm 0.48.5",
2733 | "windows_x86_64_msvc 0.48.5",
2734 | ]
2735 |
2736 | [[package]]
2737 | name = "windows-targets"
2738 | version = "0.52.6"
2739 | source = "registry+https://github.com/rust-lang/crates.io-index"
2740 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
2741 | dependencies = [
2742 | "windows_aarch64_gnullvm 0.52.6",
2743 | "windows_aarch64_msvc 0.52.6",
2744 | "windows_i686_gnu 0.52.6",
2745 | "windows_i686_gnullvm 0.52.6",
2746 | "windows_i686_msvc 0.52.6",
2747 | "windows_x86_64_gnu 0.52.6",
2748 | "windows_x86_64_gnullvm 0.52.6",
2749 | "windows_x86_64_msvc 0.52.6",
2750 | ]
2751 |
2752 | [[package]]
2753 | name = "windows-targets"
2754 | version = "0.53.3"
2755 | source = "registry+https://github.com/rust-lang/crates.io-index"
2756 | checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
2757 | dependencies = [
2758 | "windows-link",
2759 | "windows_aarch64_gnullvm 0.53.0",
2760 | "windows_aarch64_msvc 0.53.0",
2761 | "windows_i686_gnu 0.53.0",
2762 | "windows_i686_gnullvm 0.53.0",
2763 | "windows_i686_msvc 0.53.0",
2764 | "windows_x86_64_gnu 0.53.0",
2765 | "windows_x86_64_gnullvm 0.53.0",
2766 | "windows_x86_64_msvc 0.53.0",
2767 | ]
2768 |
2769 | [[package]]
2770 | name = "windows_aarch64_gnullvm"
2771 | version = "0.48.5"
2772 | source = "registry+https://github.com/rust-lang/crates.io-index"
2773 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
2774 |
2775 | [[package]]
2776 | name = "windows_aarch64_gnullvm"
2777 | version = "0.52.6"
2778 | source = "registry+https://github.com/rust-lang/crates.io-index"
2779 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
2780 |
2781 | [[package]]
2782 | name = "windows_aarch64_gnullvm"
2783 | version = "0.53.0"
2784 | source = "registry+https://github.com/rust-lang/crates.io-index"
2785 | checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
2786 |
2787 | [[package]]
2788 | name = "windows_aarch64_msvc"
2789 | version = "0.48.5"
2790 | source = "registry+https://github.com/rust-lang/crates.io-index"
2791 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
2792 |
2793 | [[package]]
2794 | name = "windows_aarch64_msvc"
2795 | version = "0.52.6"
2796 | source = "registry+https://github.com/rust-lang/crates.io-index"
2797 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
2798 |
2799 | [[package]]
2800 | name = "windows_aarch64_msvc"
2801 | version = "0.53.0"
2802 | source = "registry+https://github.com/rust-lang/crates.io-index"
2803 | checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
2804 |
2805 | [[package]]
2806 | name = "windows_i686_gnu"
2807 | version = "0.48.5"
2808 | source = "registry+https://github.com/rust-lang/crates.io-index"
2809 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
2810 |
2811 | [[package]]
2812 | name = "windows_i686_gnu"
2813 | version = "0.52.6"
2814 | source = "registry+https://github.com/rust-lang/crates.io-index"
2815 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
2816 |
2817 | [[package]]
2818 | name = "windows_i686_gnu"
2819 | version = "0.53.0"
2820 | source = "registry+https://github.com/rust-lang/crates.io-index"
2821 | checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
2822 |
2823 | [[package]]
2824 | name = "windows_i686_gnullvm"
2825 | version = "0.52.6"
2826 | source = "registry+https://github.com/rust-lang/crates.io-index"
2827 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
2828 |
2829 | [[package]]
2830 | name = "windows_i686_gnullvm"
2831 | version = "0.53.0"
2832 | source = "registry+https://github.com/rust-lang/crates.io-index"
2833 | checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
2834 |
2835 | [[package]]
2836 | name = "windows_i686_msvc"
2837 | version = "0.48.5"
2838 | source = "registry+https://github.com/rust-lang/crates.io-index"
2839 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
2840 |
2841 | [[package]]
2842 | name = "windows_i686_msvc"
2843 | version = "0.52.6"
2844 | source = "registry+https://github.com/rust-lang/crates.io-index"
2845 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
2846 |
2847 | [[package]]
2848 | name = "windows_i686_msvc"
2849 | version = "0.53.0"
2850 | source = "registry+https://github.com/rust-lang/crates.io-index"
2851 | checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
2852 |
2853 | [[package]]
2854 | name = "windows_x86_64_gnu"
2855 | version = "0.48.5"
2856 | source = "registry+https://github.com/rust-lang/crates.io-index"
2857 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
2858 |
2859 | [[package]]
2860 | name = "windows_x86_64_gnu"
2861 | version = "0.52.6"
2862 | source = "registry+https://github.com/rust-lang/crates.io-index"
2863 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
2864 |
2865 | [[package]]
2866 | name = "windows_x86_64_gnu"
2867 | version = "0.53.0"
2868 | source = "registry+https://github.com/rust-lang/crates.io-index"
2869 | checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
2870 |
2871 | [[package]]
2872 | name = "windows_x86_64_gnullvm"
2873 | version = "0.48.5"
2874 | source = "registry+https://github.com/rust-lang/crates.io-index"
2875 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
2876 |
2877 | [[package]]
2878 | name = "windows_x86_64_gnullvm"
2879 | version = "0.52.6"
2880 | source = "registry+https://github.com/rust-lang/crates.io-index"
2881 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
2882 |
2883 | [[package]]
2884 | name = "windows_x86_64_gnullvm"
2885 | version = "0.53.0"
2886 | source = "registry+https://github.com/rust-lang/crates.io-index"
2887 | checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
2888 |
2889 | [[package]]
2890 | name = "windows_x86_64_msvc"
2891 | version = "0.48.5"
2892 | source = "registry+https://github.com/rust-lang/crates.io-index"
2893 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
2894 |
2895 | [[package]]
2896 | name = "windows_x86_64_msvc"
2897 | version = "0.52.6"
2898 | source = "registry+https://github.com/rust-lang/crates.io-index"
2899 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
2900 |
2901 | [[package]]
2902 | name = "windows_x86_64_msvc"
2903 | version = "0.53.0"
2904 | source = "registry+https://github.com/rust-lang/crates.io-index"
2905 | checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
2906 |
2907 | [[package]]
2908 | name = "winnow"
2909 | version = "0.7.13"
2910 | source = "registry+https://github.com/rust-lang/crates.io-index"
2911 | checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf"
2912 | dependencies = [
2913 | "memchr",
2914 | ]
2915 |
2916 | [[package]]
2917 | name = "writeable"
2918 | version = "0.6.1"
2919 | source = "registry+https://github.com/rust-lang/crates.io-index"
2920 | checksum = "ea2f10b9bb0928dfb1b42b65e1f9e36f7f54dbdf08457afefb38afcdec4fa2bb"
2921 |
2922 | [[package]]
2923 | name = "wyz"
2924 | version = "0.5.1"
2925 | source = "registry+https://github.com/rust-lang/crates.io-index"
2926 | checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
2927 | dependencies = [
2928 | "tap",
2929 | ]
2930 |
2931 | [[package]]
2932 | name = "xxhash-rust"
2933 | version = "0.8.15"
2934 | source = "registry+https://github.com/rust-lang/crates.io-index"
2935 | checksum = "fdd20c5420375476fbd4394763288da7eb0cc0b8c11deed431a91562af7335d3"
2936 |
2937 | [[package]]
2938 | name = "yansi"
2939 | version = "1.0.1"
2940 | source = "registry+https://github.com/rust-lang/crates.io-index"
2941 | checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049"
2942 |
2943 | [[package]]
2944 | name = "yoke"
2945 | version = "0.8.0"
2946 | source = "registry+https://github.com/rust-lang/crates.io-index"
2947 | checksum = "5f41bb01b8226ef4bfd589436a297c53d118f65921786300e427be8d487695cc"
2948 | dependencies = [
2949 | "serde",
2950 | "stable_deref_trait",
2951 | "yoke-derive",
2952 | "zerofrom",
2953 | ]
2954 |
2955 | [[package]]
2956 | name = "yoke-derive"
2957 | version = "0.8.0"
2958 | source = "registry+https://github.com/rust-lang/crates.io-index"
2959 | checksum = "38da3c9736e16c5d3c8c597a9aaa5d1fa565d0532ae05e27c24aa62fb32c0ab6"
2960 | dependencies = [
2961 | "proc-macro2",
2962 | "quote",
2963 | "syn 2.0.106",
2964 | "synstructure",
2965 | ]
2966 |
2967 | [[package]]
2968 | name = "zerocopy"
2969 | version = "0.8.26"
2970 | source = "registry+https://github.com/rust-lang/crates.io-index"
2971 | checksum = "1039dd0d3c310cf05de012d8a39ff557cb0d23087fd44cad61df08fc31907a2f"
2972 | dependencies = [
2973 | "zerocopy-derive",
2974 | ]
2975 |
2976 | [[package]]
2977 | name = "zerocopy-derive"
2978 | version = "0.8.26"
2979 | source = "registry+https://github.com/rust-lang/crates.io-index"
2980 | checksum = "9ecf5b4cc5364572d7f4c329661bcc82724222973f2cab6f050a4e5c22f75181"
2981 | dependencies = [
2982 | "proc-macro2",
2983 | "quote",
2984 | "syn 2.0.106",
2985 | ]
2986 |
2987 | [[package]]
2988 | name = "zerofrom"
2989 | version = "0.1.6"
2990 | source = "registry+https://github.com/rust-lang/crates.io-index"
2991 | checksum = "50cc42e0333e05660c3587f3bf9d0478688e15d870fab3346451ce7f8c9fbea5"
2992 | dependencies = [
2993 | "zerofrom-derive",
2994 | ]
2995 |
2996 | [[package]]
2997 | name = "zerofrom-derive"
2998 | version = "0.1.6"
2999 | source = "registry+https://github.com/rust-lang/crates.io-index"
3000 | checksum = "d71e5d6e06ab090c67b5e44993ec16b72dcbaabc526db883a360057678b48502"
3001 | dependencies = [
3002 | "proc-macro2",
3003 | "quote",
3004 | "syn 2.0.106",
3005 | "synstructure",
3006 | ]
3007 |
3008 | [[package]]
3009 | name = "zeroize"
3010 | version = "1.8.1"
3011 | source = "registry+https://github.com/rust-lang/crates.io-index"
3012 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde"
3013 |
3014 | [[package]]
3015 | name = "zerotrie"
3016 | version = "0.2.2"
3017 | source = "registry+https://github.com/rust-lang/crates.io-index"
3018 | checksum = "36f0bbd478583f79edad978b407914f61b2972f5af6fa089686016be8f9af595"
3019 | dependencies = [
3020 | "displaydoc",
3021 | "yoke",
3022 | "zerofrom",
3023 | ]
3024 |
3025 | [[package]]
3026 | name = "zerovec"
3027 | version = "0.11.4"
3028 | source = "registry+https://github.com/rust-lang/crates.io-index"
3029 | checksum = "e7aa2bd55086f1ab526693ecbe444205da57e25f4489879da80635a46d90e73b"
3030 | dependencies = [
3031 | "yoke",
3032 | "zerofrom",
3033 | "zerovec-derive",
3034 | ]
3035 |
3036 | [[package]]
3037 | name = "zerovec-derive"
3038 | version = "0.11.1"
3039 | source = "registry+https://github.com/rust-lang/crates.io-index"
3040 | checksum = "5b96237efa0c878c64bd89c436f661be4e46b2f3eff1ebb976f7ef2321d2f58f"
3041 | dependencies = [
3042 | "proc-macro2",
3043 | "quote",
3044 | "syn 2.0.106",
3045 | ]
3046 |
--------------------------------------------------------------------------------