├── 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 | Volo user group 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 | [![Crates.io](https://img.shields.io/crates/v/faststr)](https://crates.io/crates/faststr) 4 | [![Documentation](https://docs.rs/faststr/badge.svg)](https://docs.rs/faststr) 5 | [![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/volo-rs/faststr) 6 | [![Website](https://img.shields.io/website?up_message=cloudwego&url=https%3A%2F%2Fwww.cloudwego.io%2F)](https://www.cloudwego.io/) 7 | [![License](https://img.shields.io/crates/l/faststr)](#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 | Volo user group 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 | Volo dev group 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 | --------------------------------------------------------------------------------