├── .dockerignore ├── .gitignore ├── src ├── entity │ ├── mod.rs │ ├── role.rs │ └── user.rs ├── query │ ├── mod.rs │ ├── role.rs │ └── user.rs ├── config │ ├── mod.rs │ ├── constants.rs │ └── env.rs ├── service │ ├── mod.rs │ ├── role.rs │ ├── file.rs │ └── user.rs ├── dto │ ├── mod.rs │ ├── custom.rs │ ├── auth.rs │ ├── role.rs │ └── user.rs ├── controller │ ├── mod.rs │ ├── file_controller.rs │ ├── root_controller.rs │ ├── user_controller.rs │ └── role_controller.rs ├── utils │ ├── mod.rs │ ├── helper.rs │ ├── encryption.rs │ ├── web_socket.rs │ ├── file.rs │ ├── swagger_docs.rs │ └── jwt.rs ├── error.rs └── main.rs ├── .vscode ├── settings.json └── launch.json ├── docker-compose.yml ├── .env ├── .env.prod ├── README.md ├── Dockerfile ├── LICENSE ├── Cargo.toml └── Cargo.lock /.dockerignore: -------------------------------------------------------------------------------- 1 | /target -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /src/entity/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod user; 2 | pub mod role; -------------------------------------------------------------------------------- /src/query/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod user; 2 | pub mod role; -------------------------------------------------------------------------------- /src/config/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod env; 2 | pub mod constants; 3 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "nuxt.isNuxtApp": false 3 | } -------------------------------------------------------------------------------- /src/service/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod file; 2 | pub mod role; 3 | pub mod user; -------------------------------------------------------------------------------- /src/dto/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod auth; 2 | pub mod custom; 3 | pub mod role; 4 | pub mod user; 5 | -------------------------------------------------------------------------------- /src/config/constants.rs: -------------------------------------------------------------------------------- 1 | lazy_static! { 2 | pub static ref BEARER: &'static str = "Bearer"; 3 | } 4 | -------------------------------------------------------------------------------- /src/controller/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod file_controller; 2 | pub mod role_controller; 3 | pub mod root_controller; 4 | pub mod user_controller; 5 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod encryption; 2 | pub mod file; 3 | pub mod jwt; 4 | pub mod helper; 5 | pub mod swagger_docs; 6 | pub mod web_socket; 7 | -------------------------------------------------------------------------------- /src/utils/helper.rs: -------------------------------------------------------------------------------- 1 | pub fn has_data(data: Option) -> bool { 2 | match data { 3 | Some(_dt) => true, 4 | None => false, 5 | } 6 | } -------------------------------------------------------------------------------- /src/dto/custom.rs: -------------------------------------------------------------------------------- 1 | use utoipa::IntoParams; 2 | 3 | #[derive(IntoParams, Serialize, Deserialize, Debug, PartialEq, Eq)] 4 | pub struct ParamRequest { 5 | pub id: i32, 6 | } -------------------------------------------------------------------------------- /src/dto/auth.rs: -------------------------------------------------------------------------------- 1 | #[derive(Debug)] 2 | pub struct AuthPayload { 3 | pub token: String 4 | } 5 | 6 | #[derive(Debug, Serialize)] 7 | pub struct TokenPayload { 8 | pub access_token: String, 9 | pub token_type: String, 10 | } 11 | -------------------------------------------------------------------------------- /src/entity/role.rs: -------------------------------------------------------------------------------- 1 | use sqlx::FromRow; 2 | 3 | #[derive(Debug, Serialize, Deserialize, Clone, FromRow)] 4 | pub struct Role { 5 | pub id: i32, 6 | pub name_th: String, 7 | pub name_en: String, 8 | pub role_code: String, 9 | pub is_deleted: bool, 10 | } 11 | 12 | impl Role { 13 | pub const TABLE: &'static str = "sys_user_role"; 14 | } 15 | -------------------------------------------------------------------------------- /src/utils/encryption.rs: -------------------------------------------------------------------------------- 1 | use sha2::{Digest, Sha512}; 2 | 3 | const BUF_SIZE: usize = 512; 4 | 5 | pub async fn hash_password(password: String) -> Option { 6 | if password.is_empty() { 7 | return None; 8 | } 9 | 10 | let mut hasher = Sha512::new(); 11 | hasher.update(password.as_bytes()); 12 | let hash = hasher.finalize(); 13 | Some(hex::encode(hash)) 14 | } 15 | -------------------------------------------------------------------------------- /src/config/env.rs: -------------------------------------------------------------------------------- 1 | use std::{env, net::IpAddr}; 2 | 3 | use clap::Parser; 4 | 5 | lazy_static! { 6 | pub static ref JWT_SECRET: String = env::var("JWT_SECRET").expect("JWT_SECRET must be set"); 7 | } 8 | 9 | #[derive(Debug, Parser)] 10 | pub struct ServerConfig { 11 | #[clap(default_value = "127.0.0.1", env)] 12 | pub host: IpAddr, 13 | #[clap(default_value = "8080", env)] 14 | pub port: u16, 15 | } 16 | -------------------------------------------------------------------------------- /docker-compose.yml: -------------------------------------------------------------------------------- 1 | version: "3.7" 2 | services: 3 | db: 4 | container_name: postgres 5 | image: postgres:latest 6 | restart: always 7 | environment: 8 | POSTGRES_DB: axum_jwt_example 9 | POSTGRES_USER: dbadmin 10 | POSTGRES_PASSWORD: dbadmin 11 | PGDATA: /var/lib/postgresql/data 12 | ports: 13 | - "5432:5432" 14 | volumes: 15 | - db-data:/var/lib/postgresql/data 16 | 17 | volumes: 18 | db-data: 19 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | PG_DATABASE=sample 2 | PG_HOST=localhost 3 | PG_PORT=36459 4 | PG_USER=appadmin 5 | PG_PASSWORD=A%21MDevel0p%40%23 6 | # Don't worry about the placeholders. Rust supports this feature. 7 | DATABASE_URL=postgres://${PG_USER}:${PG_PASSWORD}@${PG_HOST}:${PG_PORT}/${PG_DATABASE} 8 | JWT_SECRET=ce3cf10b76822168d60e806a2d6e20386d6ebbc7d544235d0c1c74cc18acd117 9 | ORIGINS=http://localhost:3000 10 | HOST=127.0.0.1 11 | PORT=8080 12 | RUST_LOG="sqlx::query=error,tower_http=debug,info" 13 | -------------------------------------------------------------------------------- /.env.prod: -------------------------------------------------------------------------------- 1 | PG_DATABASE=sample 2 | PG_HOST=localhost 3 | PG_PORT=36459 4 | PG_USER=appadmin 5 | PG_PASSWORD=A%21MDevel0p%40%23 6 | # Don't worry about the placeholders. Rust supports this feature. 7 | DATABASE_URL=postgres://${PG_USER}:${PG_PASSWORD}@${PG_HOST}:${PG_PORT}/${PG_DATABASE} 8 | JWT_SECRET=ce3cf10b76822168d60e806a2d6e20386d6ebbc7d544235d0c1c74cc18acd117 9 | ORIGINS=http://localhost:3000 10 | HOST=127.0.0.1 11 | PORT=8080 12 | RUST_LOG="sqlx::query=error,tower_http=debug,info" 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Actix JWT Sample 2 | 3 | This repository provides of: 4 | 5 | - Actix REST API 6 | - Actix CORS config 7 | - Error handling 8 | - JWT authentication 9 | - Interaction with the MySql database 10 | - Password encryption 11 | - Payload validation 12 | - OpenAPI Document `http://localhost:8080/docs/` 13 | 14 | ## Required 15 | 16 | - Rust 17 | - Docker and docker-compose or Postgresql server 18 | 19 | ## Usage 20 | 21 | - edit .env 22 | - `cargo run --release` or `debug with vscode` 23 | 24 | ## Docker build 25 | 26 | - `docker buildx build . -t aimdevgroup/sample-actix-webapi --platform linux/amd64 --push` 27 | -------------------------------------------------------------------------------- /src/controller/file_controller.rs: -------------------------------------------------------------------------------- 1 | use actix_multipart::form::MultipartForm; 2 | use actix_web::{post, web, HttpRequest, HttpResponse, Responder}; 3 | 4 | use crate::service::file::{FileService, Upload}; 5 | 6 | pub fn file_route_config(cfg: &mut web::ServiceConfig) { 7 | cfg.service(hello_file); 8 | cfg.service(upload_file); 9 | } 10 | 11 | #[post("/file")] 12 | async fn hello_file(_req: HttpRequest) -> impl Responder { 13 | HttpResponse::Ok().body("Hello file controller!") 14 | } 15 | 16 | #[post("/file/upload")] 17 | async fn upload_file(form: MultipartForm) -> HttpResponse { 18 | FileService::save_file(form).await 19 | } -------------------------------------------------------------------------------- /src/controller/root_controller.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{get, web, HttpRequest, HttpResponse, Responder}; 2 | 3 | pub fn root_route_config(cfg: &mut web::ServiceConfig) { 4 | cfg.service(hello_home); 5 | cfg.service(health_handler); 6 | } 7 | 8 | #[utoipa::path( 9 | context_path = "/api", 10 | responses( 11 | (status = 200, description = "Get Hello home controller!"), 12 | (status = 401, description = "Invalid") 13 | ) 14 | )] 15 | #[get("")] 16 | pub async fn hello_home(_req: HttpRequest) -> impl Responder { 17 | HttpResponse::Ok().body("

Hello sample api!

") 18 | } 19 | 20 | #[utoipa::path( 21 | context_path = "/api", 22 | responses( 23 | (status = 200, description = "Health check!"), 24 | (status = 401, description = "Invalid") 25 | ) 26 | )] 27 | #[get("/health")] 28 | pub async fn health_handler(_req: HttpRequest) -> impl Responder { 29 | HttpResponse::Ok().body("Healthy") 30 | } 31 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # --------------------------------------------------- 2 | # 1 - Build Stage 3 | # --------------------------------------------------- 4 | FROM rust:1.75.0 as build 5 | 6 | # Setup working directory 7 | WORKDIR /usr/src/sample_actix_webapi 8 | COPY . . 9 | COPY .env.prod .env 10 | 11 | # Build application 12 | RUN cargo install --path . 13 | 14 | # --------------------------------------------------- 15 | # 2 - Deploy Stage 16 | # --------------------------------------------------- 17 | FROM debian:bookworm-slim 18 | 19 | # Set the architecture argument (arm64, i.e. aarch64 as default) 20 | ARG ARCH=x86_64 21 | 22 | RUN apt-get update && apt-get install openssl -y 23 | 24 | # Application files 25 | COPY --from=build /usr/local/cargo/bin/sample_actix_webapi /usr/local/bin/sample_actix_webapi 26 | COPY --from=build /usr/src/sample_actix_webapi/.env /.env 27 | COPY --from=build /usr/src/sample_actix_webapi/upload /upload 28 | 29 | EXPOSE 8080 30 | 31 | CMD ["sample_actix_webapi"] -------------------------------------------------------------------------------- /src/utils/web_socket.rs: -------------------------------------------------------------------------------- 1 | use actix::{Actor, StreamHandler}; 2 | use actix_web::{web, Error, HttpRequest, HttpResponse}; 3 | use actix_web_actors::ws; 4 | 5 | struct WebSocketCls; 6 | 7 | impl Actor for WebSocketCls { 8 | type Context = ws::WebsocketContext; 9 | } 10 | 11 | /// Handler for ws::Message message 12 | impl StreamHandler> for WebSocketCls { 13 | fn handle(&mut self, msg: Result, ctx: &mut Self::Context) { 14 | match msg { 15 | Ok(ws::Message::Ping(msg)) => ctx.pong(&msg), 16 | Ok(ws::Message::Text(text)) => ctx.text(text), 17 | Ok(ws::Message::Binary(bin)) => ctx.binary(bin), 18 | _ => (), 19 | } 20 | } 21 | } 22 | 23 | pub async fn ws_index(req: HttpRequest, stream: web::Payload) -> Result { 24 | let resp = ws::start(WebSocketCls {}, &req, stream); 25 | println!("{:?}", resp); 26 | resp 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | # MIT License 2 | 3 | Copyright (c) 2021 Andrei Zolkin 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/entity/user.rs: -------------------------------------------------------------------------------- 1 | use chrono::{NaiveDate, NaiveDateTime}; 2 | use sqlx::FromRow; 3 | use utoipa::ToSchema; 4 | 5 | #[derive(Debug, Serialize, Deserialize, Clone, FromRow, ToSchema)] 6 | pub struct User { 7 | #[serde(skip_serializing)] 8 | pub id: i32, 9 | pub email: String, 10 | #[serde(skip_serializing)] 11 | pub password_hash: String, 12 | pub firstname: String, 13 | pub lastname: String, 14 | pub profile_image: String, 15 | pub role_id: i32, 16 | pub address_id: Option, 17 | pub birth_date: Option, 18 | pub phone_no: Option, 19 | pub description: Option, 20 | pub height_cm: Option, 21 | pub nationality: Option, 22 | pub gender_id: Option, 23 | pub google_auth_id: Option, 24 | pub point: i32, 25 | pub follower: i32, 26 | pub following: i32, 27 | pub is_deleted: bool, 28 | pub is_confirmed: bool, 29 | pub confirmed_user_id: Option, 30 | pub created_at: NaiveDateTime, 31 | pub updated_at: Option, 32 | } 33 | 34 | impl User { 35 | pub const TABLE: &'static str = "sys_user"; 36 | } 37 | -------------------------------------------------------------------------------- /src/dto/role.rs: -------------------------------------------------------------------------------- 1 | use validator::Validate; 2 | 3 | #[derive(Debug, Serialize, Deserialize, Clone)] 4 | pub struct GetRoleById { 5 | pub id: i32, 6 | pub name: String, 7 | pub code: String, 8 | } 9 | 10 | #[derive(Debug, Deserialize)] 11 | pub struct RequestGetRoleById { 12 | pub id: i32 13 | } 14 | 15 | #[derive(Debug, Deserialize, Validate)] 16 | pub struct CreateRoleInput { 17 | #[validate(length(min = 3))] 18 | pub name_th: String, 19 | #[validate(length(min = 3))] 20 | pub name_en: String, 21 | #[validate(length(min = 3))] 22 | pub role_code: String, 23 | } 24 | 25 | #[derive(Debug, Deserialize)] 26 | pub struct CreateRoleData { 27 | pub name_th: String, 28 | pub name_en: String, 29 | pub role_code: String, 30 | } 31 | 32 | #[derive(Debug, Deserialize, Validate)] 33 | pub struct UpdateRoleInput { 34 | pub id: i32, 35 | #[validate(length(min = 3))] 36 | pub name_th: String, 37 | #[validate(length(min = 3))] 38 | pub name_en: String, 39 | #[validate(length(min = 3))] 40 | pub role_code: String, 41 | } 42 | 43 | #[derive(Debug, Deserialize)] 44 | pub struct UpdateRoleData { 45 | pub id: i32, 46 | pub name_th: String, 47 | pub name_en: String, 48 | pub role_code: String, 49 | } 50 | 51 | -------------------------------------------------------------------------------- /src/utils/file.rs: -------------------------------------------------------------------------------- 1 | use std::io::BufWriter; 2 | 3 | use image::codecs::png::PngEncoder; 4 | use image::ImageEncoder; 5 | 6 | use fast_image_resize as fir; 7 | 8 | use crate::error::CustomError; 9 | 10 | pub async fn resize_png_from_path( 11 | width: u32, 12 | height: u32, 13 | buffer: Vec, 14 | pixel_type: fir::PixelType, 15 | ) -> Result<(), CustomError> { 16 | let src_image = fir::images::Image::from_vec_u8(width, height, buffer, pixel_type).unwrap(); 17 | 18 | // Create container for data of destination image 19 | let dst_width = 1024; 20 | let dst_height = 768; 21 | let mut dst_image = fir::images::Image::new(dst_width, dst_height, fir::PixelType::U8); 22 | 23 | // Create Resizer instance and resize source image 24 | // into buffer of destination image 25 | let mut resizer = fir::Resizer::new(); 26 | resizer.resize(&src_image, &mut dst_image, None).unwrap(); 27 | 28 | // Write destination image as PNG-file 29 | let mut result_buf = BufWriter::new(Vec::new()); 30 | let new_image = PngEncoder::new(&mut result_buf).write_image( 31 | dst_image.buffer(), 32 | dst_width, 33 | dst_height, 34 | image::ExtendedColorType::Rgba8, 35 | ); 36 | match new_image { 37 | Ok(()) => Ok(()), 38 | Err(_err) => Err(CustomError::ResizeImageError), 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/utils/swagger_docs.rs: -------------------------------------------------------------------------------- 1 | use utoipa::{ 2 | openapi::{ 3 | self, 4 | security::{Http, HttpAuthScheme, SecurityScheme}, 5 | }, 6 | Modify, OpenApi, 7 | }; 8 | 9 | use crate::controller::root_controller; 10 | use crate::controller::role_controller; 11 | use crate::controller::user_controller; 12 | 13 | #[derive(OpenApi)] 14 | #[openapi( 15 | paths( 16 | root_controller::hello_home, 17 | root_controller::health_handler, 18 | role_controller::hello_role, 19 | role_controller::get_role_by_id, 20 | role_controller::get_role_all, 21 | role_controller::post_create_role, 22 | role_controller::put_update_role, 23 | user_controller::hello_user, 24 | user_controller::get_user_by_id, 25 | user_controller::post_user_login, 26 | user_controller::post_register, 27 | user_controller::put_update_user 28 | ), 29 | components( 30 | schemas( 31 | utoipa::TupleUnit 32 | ) 33 | ), 34 | info(description = "Sample Api"), 35 | modifiers(&SecurityAddon) 36 | )] 37 | 38 | pub struct ApiDoc; 39 | 40 | struct SecurityAddon; 41 | impl Modify for SecurityAddon { 42 | fn modify(&self, openapi: &mut openapi::OpenApi) { 43 | let components = openapi.components.as_mut().unwrap(); 44 | components.add_security_scheme( 45 | "Token", 46 | SecurityScheme::Http(Http::new(HttpAuthScheme::Bearer)), 47 | ); 48 | } 49 | } -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "sample_actix_webapi" 3 | version = "2.0.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | actix = "0.13.5" 8 | actix-files = { version = "0.6.6" } 9 | actix-multipart = { version = "0.7" } 10 | actix-web = { version = "4.9" } 11 | chrono = { version = "0.4", features = ["serde"] } 12 | clap = { version = "4.5", features = ["derive", "env"] } 13 | dotenv = { version = "0.15" } 14 | jsonwebtoken = { version = "9" } 15 | lazy_static = { version = "1.5" } 16 | sanitize-filename = { version = "0.6" } 17 | serde = { version = "1.0", features = ["derive"] } 18 | serde_json = { version = "1.0" } 19 | sqlx = { version = "0.8", features = [ 20 | "runtime-tokio", 21 | "rust_decimal", 22 | "postgres", 23 | "migrate", 24 | "macros", 25 | "chrono", 26 | "uuid", 27 | ] } 28 | thiserror = { version = "2" } 29 | uuid = { version = "1.11", features = ["v4"] } 30 | utoipa-swagger-ui = { version = "8", features = ["actix-web", "debug-embed"] } 31 | validator = { version = "0.19", features = ["derive"] } 32 | utoipa = { version = "5", features = [ 33 | "actix_extras", 34 | "chrono", 35 | "decimal", 36 | "uuid", 37 | "openapi_extensions", 38 | ] } 39 | sha2 = { version = "0.10.8" } 40 | base64ct = { version = "1.6.0" } 41 | rust_xlsxwriter = { version = "0.79" } 42 | image = { version = "0.25" } 43 | fast_image_resize = { version = "5" } 44 | actix-cors = { version = "0.7" } 45 | actix-web-actors = { version = "4.3" } 46 | hex = { version = "0.4.3" } 47 | -------------------------------------------------------------------------------- /src/dto/user.rs: -------------------------------------------------------------------------------- 1 | use utoipa::ToSchema; 2 | use validator::Validate; 3 | 4 | #[derive(Validate, Debug, Default, Clone, Serialize, Deserialize, ToSchema)] 5 | pub struct UserLoginInput { 6 | #[validate(email)] 7 | pub email: String, 8 | #[validate(length(min = 6))] 9 | pub password: String 10 | } 11 | 12 | 13 | #[derive(Debug, Deserialize)] 14 | pub struct UserLoginData { 15 | pub email: String, 16 | pub password: String 17 | } 18 | 19 | #[derive(Validate, Debug, Default, Clone, Serialize, Deserialize, ToSchema)] 20 | pub struct CreateUserInput { 21 | #[validate(length(min = 4, max = 10))] 22 | pub firstname: String, 23 | #[validate(length(min = 4, max = 10))] 24 | pub lastname: String, 25 | #[validate(email)] 26 | pub email: String, 27 | #[validate(length(min = 6))] 28 | pub password: String 29 | } 30 | 31 | #[derive(Debug, Deserialize)] 32 | pub struct CreateUserData { 33 | pub firstname: String, 34 | pub lastname: String, 35 | pub email: String, 36 | pub password: String 37 | } 38 | 39 | #[derive(Validate, Debug, Default, Clone, Serialize, Deserialize, ToSchema)] 40 | pub struct UpdateUserInput { 41 | pub id: i32, 42 | #[validate(length(min = 3, max = 10))] 43 | pub firstname: String, 44 | #[validate(length(min = 3, max = 10))] 45 | pub lastname: String, 46 | } 47 | 48 | #[derive(Debug, Deserialize)] 49 | pub struct UpdateUserData { 50 | pub id: i32, 51 | pub firstname: String, 52 | pub lastname: String, 53 | } 54 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | use actix_web::HttpResponse; 2 | use serde_json::json; 3 | use thiserror::Error; 4 | 5 | #[derive(Debug, Error)] 6 | pub enum CustomError { 7 | #[error(transparent)] 8 | SqlxError(#[from] sqlx::Error), 9 | #[error(transparent)] 10 | JwtError(#[from] jsonwebtoken::errors::Error), 11 | #[error(transparent)] 12 | ValidationError(#[from] validator::ValidationErrors), 13 | #[error("Function process error")] 14 | FunctionProcessError, 15 | #[error("Wrong credentials")] 16 | WrongCredentials, 17 | #[error("Password doesn't match")] 18 | WrongPassword, 19 | #[error("Email is already taken")] 20 | DuplicateUserEmail, 21 | #[error("Search data not found")] 22 | NotFoundData, 23 | #[error("Resize file error")] 24 | ResizeImageError, 25 | } 26 | pub type ApiResult = std::result::Result; 27 | pub type ApiError = HttpResponse; 28 | 29 | impl From for ApiError { 30 | fn from(err: CustomError) -> Self { 31 | let payload = json!({"message": err.to_string()}); 32 | let status = match err { 33 | CustomError::WrongCredentials => HttpResponse::Unauthorized().json(payload), 34 | CustomError::ValidationError(_) => HttpResponse::BadRequest().json(payload), 35 | CustomError::NotFoundData => HttpResponse::NoContent().json(payload), 36 | _ => HttpResponse::InternalServerError().json(actix_web::web::Json(payload)) 37 | }; 38 | status 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/service/role.rs: -------------------------------------------------------------------------------- 1 | use sqlx::PgPool; 2 | 3 | use crate::dto::role::{ 4 | CreateRoleData, CreateRoleInput, GetRoleById, UpdateRoleData, UpdateRoleInput, 5 | }; 6 | use crate::entity::role::Role; 7 | use crate::error::ApiResult; 8 | 9 | pub struct RoleService; 10 | 11 | impl RoleService { 12 | pub async fn get_role_by_id(id: i32, pool: &PgPool) -> ApiResult { 13 | let role = Role::find_role_by_id(id, &pool).await?; 14 | Ok(GetRoleById { 15 | id: role.id, 16 | code: role.role_code, 17 | name: role.name_en, 18 | }) 19 | } 20 | 21 | pub async fn get_role_all(pool: &PgPool) -> ApiResult> { 22 | let roles = Role::find_role_all(&pool).await?; 23 | Ok(roles) 24 | } 25 | 26 | pub async fn create_role(input: CreateRoleInput, pool: &PgPool) -> ApiResult { 27 | let data = CreateRoleData { 28 | name_th: input.name_th, 29 | name_en: input.name_en, 30 | role_code: input.role_code, 31 | }; 32 | let role = Role::create_role(data, &pool).await?; 33 | Ok(role) 34 | } 35 | 36 | pub async fn update_role(input: UpdateRoleInput, pool: &PgPool) -> ApiResult { 37 | let data = UpdateRoleData { 38 | id: input.id, 39 | name_th: input.name_th, 40 | name_en: input.name_en, 41 | role_code: input.role_code, 42 | }; 43 | let role = Role::update_role(data, &pool).await?; 44 | Ok(role) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug executable 'sample_actix_webapi'", 11 | "cargo": { 12 | "args": [ 13 | "build", 14 | "--bin=sample_actix_webapi", 15 | "--package=sample_actix_webapi" 16 | ], 17 | "filter": { 18 | "name": "sample_actix_webapi", 19 | "kind": "bin" 20 | } 21 | }, 22 | "args": [], 23 | "cwd": "${workspaceFolder}" 24 | }, 25 | { 26 | "type": "lldb", 27 | "request": "launch", 28 | "name": "Debug unit tests in executable 'sample_actix_webapi'", 29 | "cargo": { 30 | "args": [ 31 | "test", 32 | "--no-run", 33 | "--bin=sample_actix_webapi", 34 | "--package=sample_actix_webapi" 35 | ], 36 | "filter": { 37 | "name": "sample_actix_webapi", 38 | "kind": "bin" 39 | } 40 | }, 41 | "args": [], 42 | "cwd": "${workspaceFolder}" 43 | } 44 | ] 45 | } -------------------------------------------------------------------------------- /src/query/role.rs: -------------------------------------------------------------------------------- 1 | use chrono::Local; 2 | use sqlx::PgPool; 3 | 4 | use crate::{ 5 | error::ApiResult, 6 | entity::role::Role, dto::role::{CreateRoleData, UpdateRoleData} 7 | }; 8 | 9 | impl Role { 10 | pub async fn find_role_by_id(id: i32, pool: &PgPool) -> ApiResult { 11 | let sql = format!("SELECT * FROM {} WHERE id = $1", Role::TABLE); 12 | Ok(sqlx::query_as(&sql).bind(id).fetch_one(pool).await?) 13 | } 14 | 15 | pub async fn find_role_all(pool: &PgPool) -> ApiResult> { 16 | let sql = format!("SELECT * FROM {}", Role::TABLE); 17 | Ok(sqlx::query_as(&sql).fetch_all(pool).await?) 18 | } 19 | 20 | pub async fn create_role(data: CreateRoleData, pool: &PgPool) -> ApiResult { 21 | let sql = format!( 22 | " 23 | INSERT INTO {} (name_th, name_en, role_code, created_at, updated_at) 24 | VALUES ($1, $2, $3, $4, $5) 25 | RETURNING * 26 | ", 27 | Role::TABLE 28 | ); 29 | Ok(sqlx::query_as(&sql) 30 | .bind(data.name_th) 31 | .bind(data.name_en) 32 | .bind(data.role_code) 33 | .bind(Local::now()) 34 | .bind(Local::now()) 35 | .fetch_one(pool) 36 | .await?) 37 | } 38 | 39 | pub async fn update_role(data: UpdateRoleData, pool: &PgPool) -> ApiResult { 40 | let sql = format!( 41 | " 42 | UPDATE {} 43 | SET name_th = $1, name_en = $2, role_code = $3) 44 | RETURNING * 45 | ", 46 | Role::TABLE 47 | ); 48 | Ok(sqlx::query_as(&sql) 49 | .bind(data.name_th) 50 | .bind(data.name_en) 51 | .bind(data.role_code) 52 | .bind(Local::now()) 53 | .fetch_one(pool) 54 | .await?) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/service/file.rs: -------------------------------------------------------------------------------- 1 | use actix_multipart::form::{tempfile::TempFile, MultipartForm}; 2 | use actix_web::{web, HttpResponse}; 3 | use serde_json::json; 4 | use std::path::PathBuf; 5 | use uuid::Uuid; 6 | 7 | #[derive(MultipartForm)] 8 | pub struct Upload { 9 | file: TempFile, 10 | } 11 | 12 | pub struct FileService; 13 | 14 | impl FileService { 15 | pub async fn save_file(form: MultipartForm) -> HttpResponse { 16 | const MAX_FILE_SIZE: usize = 1024 * 1024 * 100; // 100 MB 17 | match form.file.size { 18 | 0 => return HttpResponse::BadRequest().finish(), 19 | length if length > MAX_FILE_SIZE => { 20 | return HttpResponse::BadRequest().body(format!( 21 | "The uploaded file is too large. Maximum size is {} bytes.", 22 | MAX_FILE_SIZE 23 | )); 24 | } 25 | _ => {} 26 | }; 27 | let temp_file_path = form.file.file.path(); 28 | let file_name: &str = form 29 | .file 30 | .file_name 31 | .as_ref() 32 | .map(|m| m.as_ref()) 33 | .unwrap_or("null"); 34 | 35 | let file_type = file_name.split(".").last().unwrap(); 36 | let file_uuid = Uuid::new_v4(); 37 | let new_filename = file_uuid.to_string() + file_type; 38 | 39 | let mut file_path = PathBuf::from("./upload/file"); 40 | file_path.push(&sanitize_filename::sanitize(&new_filename)); 41 | 42 | match std::fs::rename(temp_file_path, file_path) { 43 | Ok(_) => { 44 | let json = json!({"filename": new_filename}); 45 | HttpResponse::Ok().json(web::Json(json)) 46 | }, 47 | Err(_) => { 48 | let msg = format!("Upload file {} error.", file_name); 49 | let json = json!({"message": msg}); 50 | HttpResponse::InternalServerError().json(web::Json(json)) 51 | }, 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /src/utils/jwt.rs: -------------------------------------------------------------------------------- 1 | use actix_web::HttpRequest; 2 | use chrono::{Duration, Utc}; 3 | use jsonwebtoken::{DecodingKey, EncodingKey, Header, Validation}; 4 | 5 | use crate::{ 6 | config::env::JWT_SECRET, 7 | entity::user::User, 8 | error::{ApiResult, CustomError}, 9 | }; 10 | 11 | #[derive(Debug, Deserialize, Serialize, Clone)] 12 | pub struct Claims { 13 | pub id: i32, 14 | pub email: String, 15 | pub role_code: String, 16 | pub exp: i64, 17 | pub iat: i64, 18 | } 19 | 20 | impl Claims { 21 | pub fn new(id: i32, email: String, role_code: String) -> Self { 22 | let iat = Utc::now(); 23 | let exp = iat + Duration::hours(24); 24 | Self { 25 | id: id, 26 | email: email, 27 | role_code: role_code, 28 | iat: iat.timestamp(), 29 | exp: exp.timestamp(), 30 | } 31 | } 32 | } 33 | 34 | pub fn jwt_sign(input: User, role_code: String) -> ApiResult { 35 | Ok(jsonwebtoken::encode( 36 | &Header::default(), 37 | &Claims::new(input.id, input.email, role_code), 38 | &EncodingKey::from_secret(JWT_SECRET.as_bytes()), 39 | )?) 40 | } 41 | 42 | pub fn jwt_verify(req: HttpRequest) -> Result { 43 | let token_access = authorize(req); 44 | match token_access { 45 | Ok(token_data) => { 46 | let token_str = token_data.as_str(); 47 | let token_mut = token_str.replace("Bearer ", ""); 48 | let user = jsonwebtoken::decode::( 49 | token_mut.as_str(), 50 | &DecodingKey::from_secret(JWT_SECRET.as_bytes()), 51 | &Validation::default(), 52 | ) 53 | .map(|data| data.claims)?; 54 | Ok(user) 55 | } 56 | Err(err) => Err(err), 57 | } 58 | } 59 | 60 | fn authorize(req: HttpRequest) -> Result { 61 | if let Some(_jwt) = get_authorized(&req) { 62 | Ok(String::from(_jwt)) 63 | } else { 64 | Err(CustomError::WrongCredentials) 65 | } 66 | } 67 | 68 | fn get_authorized<'a>(req: &'a HttpRequest) -> Option<&'a str> { 69 | req.headers().get("Authorization")?.to_str().ok() 70 | } 71 | -------------------------------------------------------------------------------- /src/query/user.rs: -------------------------------------------------------------------------------- 1 | use chrono::Local; 2 | use sqlx::PgPool; 3 | 4 | use crate::{ 5 | dto::user::{CreateUserData, UpdateUserData, UserLoginData}, 6 | entity::user::User, 7 | error::ApiResult, 8 | }; 9 | 10 | impl User { 11 | pub async fn find_user_by_id(id: i32, pool: &PgPool) -> ApiResult> { 12 | let sql = format!("SELECT * FROM {} WHERE id = $1", User::TABLE); 13 | Ok(sqlx::query_as(&sql).bind(id).fetch_optional(pool).await?) 14 | } 15 | 16 | pub async fn find_user_login(data: UserLoginData, pool: &PgPool) -> ApiResult> { 17 | let sql = format!( 18 | "SELECT * FROM {} WHERE phone_no = $1 AND password_hash = $2", 19 | User::TABLE, 20 | ); 21 | Ok(sqlx::query_as(&sql) 22 | .bind(data.email) 23 | .bind(data.password) 24 | .fetch_optional(pool) 25 | .await?) 26 | } 27 | 28 | pub async fn find_user_by_email(email: &str, pool: &PgPool) -> ApiResult> { 29 | let sql = format!("SELECT * FROM {} WHERE phone_no = $1", User::TABLE); 30 | Ok(sqlx::query_as(&sql) 31 | .bind(email) 32 | .fetch_optional(pool) 33 | .await?) 34 | } 35 | 36 | pub async fn create_user(data: CreateUserData, pool: &PgPool) -> ApiResult { 37 | let sql = format!( 38 | " 39 | INSERT INTO {} (firstname, lastname, role_id, profile_image, email, password_hash, point, follower, following, is_deleted, is_confirmed, created_at) 40 | VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12) 41 | RETURNING * 42 | ", 43 | User::TABLE 44 | ); 45 | let excutor = sqlx::query(&sql) 46 | .bind(data.firstname) 47 | .bind(data.lastname) 48 | .bind(1) 49 | .bind("no_profile.png") 50 | .bind(data.email) 51 | .bind(data.password) 52 | .bind(0) 53 | .bind(0) 54 | .bind(0) 55 | .bind(false) 56 | .bind(false) 57 | .bind(Local::now()) 58 | .execute(pool) 59 | .await?; 60 | Ok(excutor.rows_affected()) 61 | } 62 | 63 | pub async fn update_user(data: UpdateUserData, pool: &PgPool) -> ApiResult { 64 | let sql = format!( 65 | " 66 | UPDATE {} 67 | SET firstname = $1, lastname = $2, updated_at = $3 68 | WHERE id = $4 69 | RETURNING * 70 | ", 71 | User::TABLE 72 | ); 73 | let excutor = sqlx::query(&sql) 74 | .bind(data.firstname) 75 | .bind(data.lastname) 76 | .bind(Local::now()) 77 | .bind(data.id) 78 | .execute(pool) 79 | .await?; 80 | Ok(excutor.rows_affected()) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate lazy_static; 3 | #[macro_use] 4 | extern crate serde; 5 | 6 | use std::fs as stdfs; 7 | use std::time::Duration; 8 | 9 | use actix_cors::Cors; 10 | use actix_files as fs; 11 | use actix_web::{http::header, middleware::Logger, web, App, HttpServer}; 12 | use controller::{file_controller, role_controller, root_controller, user_controller}; 13 | use dotenv::dotenv; 14 | use sqlx::postgres::{PgPool, PgPoolOptions}; 15 | use utils::{swagger_docs::ApiDoc, web_socket::ws_index}; 16 | use utoipa::OpenApi; 17 | use utoipa_swagger_ui::SwaggerUi; 18 | 19 | mod config; 20 | mod controller; 21 | mod dto; 22 | mod entity; 23 | mod error; 24 | mod query; 25 | mod service; 26 | mod utils; 27 | 28 | pub struct PgState { 29 | pub db: PgPool, 30 | } 31 | 32 | #[actix_web::main] 33 | async fn main() -> std::io::Result<()> { 34 | dotenv().ok(); 35 | let origins = std::env::var("ORIGINS").expect("ORIGINS must be set"); 36 | let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set"); 37 | let pool = match PgPoolOptions::new() 38 | .max_connections(10) 39 | .connect(&database_url) 40 | .await 41 | { 42 | Ok(pool) => { 43 | println!("Connection to the database is successful !"); 44 | pool 45 | } 46 | Err(err) => { 47 | println!("Failed to connect to the database: {:?}", err); 48 | std::process::exit(1); 49 | } 50 | }; 51 | 52 | let dir_creator_image = stdfs::create_dir("./upload/image"); 53 | match dir_creator_image { 54 | Ok(()) => {} 55 | Err(_err) => { 56 | println!("Skip create directory /upload/image, directory is exist.") 57 | } 58 | } 59 | 60 | let dir_creator_file = stdfs::create_dir("./upload/file"); 61 | match dir_creator_file { 62 | Ok(()) => {} 63 | Err(_err) => { 64 | println!("Skip create directory /upload/file, directory is exist.") 65 | } 66 | } 67 | let openapi = ApiDoc::openapi(); 68 | HttpServer::new(move || { 69 | let cors = Cors::default() 70 | .allowed_origin(&origins) 71 | .allowed_methods(vec!["GET", "POST", "PATCH", "DELETE"]) 72 | .allowed_headers(vec![ 73 | header::CONTENT_TYPE, 74 | header::AUTHORIZATION, 75 | header::ACCEPT, 76 | ]) 77 | .supports_credentials(); 78 | App::new() 79 | .app_data(web::Data::new(PgState { db: pool.clone() })) 80 | .route("/ws/", web::get().to(ws_index)) 81 | .service( 82 | web::scope("/api") 83 | .configure(root_controller::root_route_config) 84 | .configure(file_controller::file_route_config) 85 | .configure(role_controller::role_route_config) 86 | .configure(user_controller::user_route_config), 87 | ) 88 | .service(fs::Files::new("/upload", "./upload").use_last_modified(true)) 89 | .service(SwaggerUi::new("/docs/{_:.*}").url("/api-docs/openapi.json", openapi.clone())) 90 | .wrap(cors) 91 | .wrap(Logger::default()) 92 | }) 93 | .client_request_timeout(Duration::from_secs(15)) 94 | .workers(2) 95 | .bind(("0.0.0.0", 8080))? 96 | .run() 97 | .await 98 | } 99 | -------------------------------------------------------------------------------- /src/service/user.rs: -------------------------------------------------------------------------------- 1 | use sqlx::PgPool; 2 | 3 | use crate::dto::user::{ 4 | CreateUserData, CreateUserInput, UpdateUserData, UpdateUserInput, UserLoginData, UserLoginInput, 5 | }; 6 | use crate::entity::user::User; 7 | use crate::error::{ApiResult, CustomError}; 8 | use crate::utils::encryption::hash_password; 9 | use crate::utils::helper::has_data; 10 | 11 | pub struct UserService; 12 | 13 | impl UserService { 14 | pub async fn get_user_by_id(id: i32, pool: &PgPool) -> ApiResult { 15 | let result = User::find_user_by_id(id, &pool).await?; 16 | match result { 17 | Some(data) => Ok(data), 18 | None => Err(CustomError::NotFoundData), 19 | } 20 | } 21 | 22 | pub async fn get_user_login(input: UserLoginInput, pool: &PgPool) -> ApiResult { 23 | let pwd_hash = hash_password(input.password.clone()).await; 24 | 25 | if pwd_hash.is_none() { 26 | return Err(CustomError::FunctionProcessError); 27 | } 28 | 29 | let data = UserLoginData { 30 | email: input.email.clone(), 31 | password: pwd_hash.unwrap(), 32 | }; 33 | let result = User::find_user_login(data, &pool).await?; 34 | match result { 35 | Some(data) => Ok(data), 36 | None => Err(CustomError::NotFoundData), 37 | } 38 | } 39 | 40 | pub async fn create_user(input: CreateUserInput, pool: &PgPool) -> ApiResult { 41 | let find_user = User::find_user_by_email(&input.email, &pool).await; 42 | let user_found: Result = match find_user { 43 | Ok(user_option) => Ok(has_data(user_option)), 44 | Err(_err) => Err(_err), 45 | }; 46 | let pwd_hash = hash_password(input.password.clone()).await; 47 | 48 | if pwd_hash.is_none() { 49 | return Err(CustomError::FunctionProcessError); 50 | } 51 | 52 | match user_found { 53 | Ok(found) => { 54 | if found { 55 | return Err(CustomError::DuplicateUserEmail); 56 | } 57 | let data = CreateUserData { 58 | firstname: input.firstname, 59 | lastname: input.lastname, 60 | email: input.email, 61 | password: pwd_hash.unwrap(), 62 | }; 63 | let result = User::create_user(data, &pool).await; 64 | match result { 65 | Ok(_data) => Ok(_data), 66 | Err(err) => Err(err), 67 | } 68 | } 69 | Err(_err) => Err(_err), 70 | } 71 | } 72 | 73 | pub async fn update_user(input: UpdateUserInput, pool: &PgPool) -> ApiResult { 74 | let find_user = User::find_user_by_id(input.id, &pool).await; 75 | let user_found: Result = match find_user { 76 | Ok(user_option) => Ok(has_data(user_option)), 77 | Err(_err) => Err(_err), 78 | }; 79 | match user_found { 80 | Ok(found) => { 81 | if found { 82 | return Err(CustomError::DuplicateUserEmail); 83 | } 84 | let data = UpdateUserData { 85 | id: input.id, 86 | firstname: input.firstname, 87 | lastname: input.lastname, 88 | }; 89 | let result = User::update_user(data, &pool).await; 90 | match result { 91 | Ok(data) => Ok(data), 92 | Err(err) => Err(err), 93 | } 94 | } 95 | Err(_err) => Err(_err), 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/controller/user_controller.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{get, post, put, web::{self, Json, Path}, HttpRequest, HttpResponse, Responder}; 2 | use serde_json::json; 3 | 4 | use crate::{ 5 | dto::{ 6 | custom::ParamRequest, 7 | user::{CreateUserInput, UpdateUserInput, UserLoginInput}, 8 | }, 9 | service::user::UserService, 10 | utils::jwt::{jwt_sign, jwt_verify}, 11 | PgState, 12 | }; 13 | 14 | pub fn user_route_config(cfg: &mut web::ServiceConfig) { 15 | cfg.service(hello_user); 16 | cfg.service(get_user_by_id); 17 | cfg.service(post_user_login); 18 | cfg.service(post_register); 19 | cfg.service(put_update_user); 20 | } 21 | 22 | #[utoipa::path( 23 | context_path = "/api", 24 | responses( 25 | (status = 200, description = "Get Hello user controller!"), 26 | (status = 401, description = "Invalid") 27 | ) 28 | )] 29 | #[get("/user")] 30 | async fn hello_user() -> impl Responder { 31 | HttpResponse::Ok().body("Hello user controller!") 32 | } 33 | 34 | #[utoipa::path( 35 | context_path = "/api", 36 | responses( 37 | (status = 200, description = "Get user by id!"), 38 | (status = 401, description = "Invalid") 39 | ), 40 | params( 41 | ParamRequest, 42 | ), 43 | )] 44 | #[get("/user/getById/{id}")] 45 | async fn get_user_by_id( 46 | _req: HttpRequest, 47 | path: Path, 48 | db_state: web::Data, 49 | ) -> impl Responder { 50 | let param = path.into_inner(); 51 | let result = UserService::get_user_by_id(param.id, &db_state.db).await; 52 | match result { 53 | Ok(data) => HttpResponse::Ok().json(data), 54 | Err(_err) => { 55 | let json = json!({"message": _err.to_string()}); 56 | HttpResponse::Unauthorized().json(web::Json(json)) 57 | } 58 | } 59 | } 60 | 61 | #[utoipa::path( 62 | context_path = "/api", 63 | responses( 64 | (status = 200, description = "Login !"), 65 | (status = 409, description = "Invalid Request Format") 66 | ), 67 | request_body(content = UserLoginInput, example = json!({"email": "johndoe@example.com", "password": "password123"})), 68 | )] 69 | #[post("/user/login")] 70 | async fn post_user_login( 71 | _req: HttpRequest, 72 | body: Json, 73 | db_state: web::Data, 74 | ) -> impl Responder { 75 | let input = UserLoginInput { 76 | email: body.email.clone(), 77 | password: body.password.clone(), 78 | }; 79 | let result = UserService::get_user_login(input, &db_state.db).await; 80 | match result { 81 | Ok(data) => { 82 | let sign_token_result = jwt_sign(data, String::from("user")); 83 | match sign_token_result { 84 | Ok(token) => { 85 | let json = json!({"token": token}); 86 | HttpResponse::Ok().json(Json(json)) 87 | } 88 | Err(_err) => { 89 | let json = json!({"message": "Internal server error."}); 90 | HttpResponse::Unauthorized().json(Json(json)) 91 | } 92 | } 93 | } 94 | Err(_err) => { 95 | let json = json!({"message": _err.to_string()}); 96 | HttpResponse::BadRequest().json(Json(json)) 97 | } 98 | } 99 | } 100 | 101 | #[utoipa::path( 102 | context_path = "/api", 103 | responses( 104 | (status = 200, description = "Create user !"), 105 | (status = 409, description = "Invalid Request Format") 106 | ), 107 | request_body(content = CreateUserInput, example = json!({"email": "johndoe@example.com", "password": "password123", "firstname": "Mr.Sun", "lastname": "Hapoon"})), 108 | )] 109 | #[post("/user/register")] 110 | async fn post_register( 111 | _req: HttpRequest, 112 | body: Json, 113 | db_state: web::Data, 114 | ) -> impl Responder { 115 | let input = CreateUserInput { 116 | email: body.email.clone(), 117 | password: body.password.clone(), 118 | firstname: body.firstname.clone(), 119 | lastname: body.lastname.clone(), 120 | }; 121 | let result = UserService::create_user(input, &db_state.db).await; 122 | match result { 123 | Ok(_data) => HttpResponse::Created().finish(), 124 | Err(_err) => { 125 | let json = json!({"message": _err.to_string()}); 126 | HttpResponse::BadRequest().json(web::Json(json)) 127 | } 128 | } 129 | } 130 | 131 | #[utoipa::path( 132 | context_path = "/api", 133 | responses( 134 | (status = 200, description = "Update user !"), 135 | (status = 409, description = "Invalid Request Format") 136 | ), 137 | request_body(content = UpdateUserInput, example = json!({"id": 1, "firstname": "Mr.Sun", "lastname": "Hapoon"})), 138 | )] 139 | #[put("/user/update")] 140 | async fn put_update_user( 141 | _req: HttpRequest, 142 | body: Json, 143 | db_state: web::Data, 144 | ) -> impl Responder { 145 | let authorize = jwt_verify(_req); 146 | match authorize { 147 | Ok(_user_claim) => { 148 | let input = UpdateUserInput { 149 | id: body.id.clone(), 150 | firstname: body.firstname.clone(), 151 | lastname: body.lastname.clone(), 152 | }; 153 | let result = UserService::update_user(input, &db_state.db).await; 154 | match result { 155 | Ok(_data) => HttpResponse::Ok().finish(), 156 | Err(_err) => { 157 | let json = json!({"message": "Update data error."}); 158 | HttpResponse::BadRequest().json(web::Json(json)) 159 | } 160 | } 161 | } 162 | Err(_err) => { 163 | let json = json!({"message": "Unauthorized."}); 164 | HttpResponse::Unauthorized().json(web::Json(json)) 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /src/controller/role_controller.rs: -------------------------------------------------------------------------------- 1 | use actix_web::{get, post, put, web, HttpRequest, HttpResponse, Responder}; 2 | use serde_json::json; 3 | 4 | use crate::{ 5 | dto::{ 6 | custom::ParamRequest, 7 | role::{CreateRoleInput, UpdateRoleInput}, 8 | }, 9 | service::role::RoleService, 10 | utils::jwt::jwt_verify, 11 | PgState, 12 | }; 13 | 14 | pub fn role_route_config(cfg: &mut web::ServiceConfig) { 15 | cfg.service(hello_role); 16 | cfg.service(get_role_by_id); 17 | cfg.service(get_role_all); 18 | cfg.service(post_create_role); 19 | cfg.service(put_update_role); 20 | } 21 | 22 | #[utoipa::path( 23 | context_path = "/api", 24 | responses( 25 | (status = 200, description = "Get role home!"), 26 | (status = 401, description = "Invalid") 27 | ), 28 | )] 29 | #[get("/role")] 30 | async fn hello_role(_req: HttpRequest) -> impl Responder { 31 | HttpResponse::Ok().body("Hello role controller!") 32 | } 33 | 34 | #[utoipa::path( 35 | context_path = "/api", 36 | responses( 37 | (status = 200, description = "Get role by id!"), 38 | (status = 401, description = "Invalid") 39 | ), 40 | params( 41 | ParamRequest, 42 | ), 43 | )] 44 | #[get("/role/getById/{id}")] 45 | async fn get_role_by_id( 46 | _req: HttpRequest, 47 | path: web::Path, 48 | db_state: web::Data, 49 | ) -> HttpResponse { 50 | let authorize = jwt_verify(_req); 51 | match authorize { 52 | Ok(_user_claim) => { 53 | let param = path.into_inner(); 54 | let result = RoleService::get_role_by_id(param.id, &db_state.db).await; 55 | match result { 56 | Ok(data) => HttpResponse::Ok().json(data), 57 | Err(_err) => { 58 | let json = json!({"message": _err.to_string()}); 59 | HttpResponse::Unauthorized().json(actix_web::web::Json(json)) 60 | } 61 | } 62 | } 63 | Err(_err) => { 64 | let json = json!({"message": "Unauthorized."}); 65 | HttpResponse::Unauthorized().json(actix_web::web::Json(json)) 66 | } 67 | } 68 | } 69 | 70 | #[utoipa::path( 71 | context_path = "/api", 72 | responses( 73 | (status = 200, description = "Get role all !"), 74 | (status = 401, description = "Invalid") 75 | ), 76 | )] 77 | #[get("/role/getAll")] 78 | async fn get_role_all(_req: HttpRequest, db_state: web::Data) -> HttpResponse { 79 | let authorize = jwt_verify(_req); 80 | match authorize { 81 | Ok(_user_claim) => { 82 | let result = RoleService::get_role_all(&db_state.db).await; 83 | match result { 84 | Ok(data) => HttpResponse::Ok().json(data), 85 | Err(_err) => { 86 | let json = json!({"message": _err.to_string()}); 87 | HttpResponse::Unauthorized().json(actix_web::web::Json(json)) 88 | } 89 | } 90 | } 91 | Err(_err) => { 92 | let json = json!({"message": "Unauthorized."}); 93 | HttpResponse::Unauthorized().json(actix_web::web::Json(json)) 94 | } 95 | } 96 | } 97 | 98 | #[utoipa::path( 99 | context_path = "/api", 100 | responses( 101 | (status = 200, description = "Create !"), 102 | (status = 409, description = "Invalid Request Format") 103 | ), 104 | request_body(content = String, example = json!({"name_th": "ผู้ใช้งาน", "name_en": "User", "role_code": " user"})), 105 | )] 106 | #[post("/role/create")] 107 | async fn post_create_role( 108 | _req: HttpRequest, 109 | body: web::Json, 110 | db_state: web::Data, 111 | ) -> HttpResponse { 112 | let authorize = jwt_verify(_req); 113 | match authorize { 114 | Ok(_user_claim) => { 115 | let input = CreateRoleInput { 116 | name_th: body.name_th.clone(), 117 | name_en: body.name_en.clone(), 118 | role_code: body.role_code.clone(), 119 | }; 120 | let result = RoleService::create_role(input, &db_state.db).await; 121 | match result { 122 | Ok(data) => HttpResponse::Ok().json(data), 123 | Err(_err) => HttpResponse::BadRequest().body(_err.to_string()), 124 | } 125 | } 126 | Err(_err) => { 127 | let json = json!({"message": "Unauthorized."}); 128 | HttpResponse::Unauthorized().json(actix_web::web::Json(json)) 129 | } 130 | } 131 | } 132 | 133 | #[utoipa::path( 134 | context_path = "/api", 135 | responses( 136 | (status = 200, description = "Update role !"), 137 | (status = 409, description = "Invalid Request Format") 138 | ), 139 | request_body(content = String, example = json!({"id": 1, "name_th": "ผู้ใช้งาน", "name_en": "User", "role_code": " user"})), 140 | )] 141 | #[put("/role/update")] 142 | async fn put_update_role( 143 | _req: HttpRequest, 144 | body: web::Json, 145 | db_state: web::Data, 146 | ) -> HttpResponse { 147 | let authorize = jwt_verify(_req); 148 | match authorize { 149 | Ok(_user_claim) => { 150 | let input = UpdateRoleInput { 151 | id: body.id.clone(), 152 | name_th: body.name_th.clone(), 153 | name_en: body.name_en.clone(), 154 | role_code: body.role_code.clone(), 155 | }; 156 | let result = RoleService::update_role(input, &db_state.db).await; 157 | match result { 158 | Ok(data) => HttpResponse::Ok().json(data), 159 | Err(_err) => HttpResponse::BadRequest().body(_err.to_string()), 160 | } 161 | } 162 | Err(_err) => { 163 | let json = json!({"message": "Unauthorized."}); 164 | HttpResponse::Unauthorized().json(actix_web::web::Json(json)) 165 | } 166 | } 167 | } 168 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "actix" 7 | version = "0.13.5" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "de7fa236829ba0841304542f7614c42b80fca007455315c45c785ccfa873a85b" 10 | dependencies = [ 11 | "actix-macros", 12 | "actix-rt", 13 | "actix_derive", 14 | "bitflags 2.6.0", 15 | "bytes", 16 | "crossbeam-channel", 17 | "futures-core", 18 | "futures-sink", 19 | "futures-task", 20 | "futures-util", 21 | "log", 22 | "once_cell", 23 | "parking_lot", 24 | "pin-project-lite", 25 | "smallvec", 26 | "tokio", 27 | "tokio-util", 28 | ] 29 | 30 | [[package]] 31 | name = "actix-codec" 32 | version = "0.5.2" 33 | source = "registry+https://github.com/rust-lang/crates.io-index" 34 | checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" 35 | dependencies = [ 36 | "bitflags 2.6.0", 37 | "bytes", 38 | "futures-core", 39 | "futures-sink", 40 | "memchr", 41 | "pin-project-lite", 42 | "tokio", 43 | "tokio-util", 44 | "tracing", 45 | ] 46 | 47 | [[package]] 48 | name = "actix-cors" 49 | version = "0.7.0" 50 | source = "registry+https://github.com/rust-lang/crates.io-index" 51 | checksum = "f9e772b3bcafe335042b5db010ab7c09013dad6eac4915c91d8d50902769f331" 52 | dependencies = [ 53 | "actix-utils", 54 | "actix-web", 55 | "derive_more", 56 | "futures-util", 57 | "log", 58 | "once_cell", 59 | "smallvec", 60 | ] 61 | 62 | [[package]] 63 | name = "actix-files" 64 | version = "0.6.6" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "0773d59061dedb49a8aed04c67291b9d8cf2fe0b60130a381aab53c6dd86e9be" 67 | dependencies = [ 68 | "actix-http", 69 | "actix-service", 70 | "actix-utils", 71 | "actix-web", 72 | "bitflags 2.6.0", 73 | "bytes", 74 | "derive_more", 75 | "futures-core", 76 | "http-range", 77 | "log", 78 | "mime", 79 | "mime_guess", 80 | "percent-encoding", 81 | "pin-project-lite", 82 | "v_htmlescape", 83 | ] 84 | 85 | [[package]] 86 | name = "actix-http" 87 | version = "3.9.0" 88 | source = "registry+https://github.com/rust-lang/crates.io-index" 89 | checksum = "d48f96fc3003717aeb9856ca3d02a8c7de502667ad76eeacd830b48d2e91fac4" 90 | dependencies = [ 91 | "actix-codec", 92 | "actix-rt", 93 | "actix-service", 94 | "actix-utils", 95 | "ahash 0.8.11", 96 | "base64 0.22.1", 97 | "bitflags 2.6.0", 98 | "brotli", 99 | "bytes", 100 | "bytestring", 101 | "derive_more", 102 | "encoding_rs", 103 | "flate2", 104 | "futures-core", 105 | "h2", 106 | "http", 107 | "httparse", 108 | "httpdate", 109 | "itoa", 110 | "language-tags", 111 | "local-channel", 112 | "mime", 113 | "percent-encoding", 114 | "pin-project-lite", 115 | "rand", 116 | "sha1", 117 | "smallvec", 118 | "tokio", 119 | "tokio-util", 120 | "tracing", 121 | "zstd", 122 | ] 123 | 124 | [[package]] 125 | name = "actix-macros" 126 | version = "0.2.4" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" 129 | dependencies = [ 130 | "quote", 131 | "syn 2.0.89", 132 | ] 133 | 134 | [[package]] 135 | name = "actix-multipart" 136 | version = "0.7.2" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "d5118a26dee7e34e894f7e85aa0ee5080ae4c18bf03c0e30d49a80e418f00a53" 139 | dependencies = [ 140 | "actix-multipart-derive", 141 | "actix-utils", 142 | "actix-web", 143 | "derive_more", 144 | "futures-core", 145 | "futures-util", 146 | "httparse", 147 | "local-waker", 148 | "log", 149 | "memchr", 150 | "mime", 151 | "rand", 152 | "serde", 153 | "serde_json", 154 | "serde_plain", 155 | "tempfile", 156 | "tokio", 157 | ] 158 | 159 | [[package]] 160 | name = "actix-multipart-derive" 161 | version = "0.7.0" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "e11eb847f49a700678ea2fa73daeb3208061afa2b9d1a8527c03390f4c4a1c6b" 164 | dependencies = [ 165 | "darling", 166 | "parse-size", 167 | "proc-macro2", 168 | "quote", 169 | "syn 2.0.89", 170 | ] 171 | 172 | [[package]] 173 | name = "actix-router" 174 | version = "0.5.3" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8" 177 | dependencies = [ 178 | "bytestring", 179 | "cfg-if", 180 | "http", 181 | "regex", 182 | "regex-lite", 183 | "serde", 184 | "tracing", 185 | ] 186 | 187 | [[package]] 188 | name = "actix-rt" 189 | version = "2.10.0" 190 | source = "registry+https://github.com/rust-lang/crates.io-index" 191 | checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" 192 | dependencies = [ 193 | "futures-core", 194 | "tokio", 195 | ] 196 | 197 | [[package]] 198 | name = "actix-server" 199 | version = "2.5.0" 200 | source = "registry+https://github.com/rust-lang/crates.io-index" 201 | checksum = "7ca2549781d8dd6d75c40cf6b6051260a2cc2f3c62343d761a969a0640646894" 202 | dependencies = [ 203 | "actix-rt", 204 | "actix-service", 205 | "actix-utils", 206 | "futures-core", 207 | "futures-util", 208 | "mio", 209 | "socket2", 210 | "tokio", 211 | "tracing", 212 | ] 213 | 214 | [[package]] 215 | name = "actix-service" 216 | version = "2.0.2" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "3b894941f818cfdc7ccc4b9e60fa7e53b5042a2e8567270f9147d5591893373a" 219 | dependencies = [ 220 | "futures-core", 221 | "paste", 222 | "pin-project-lite", 223 | ] 224 | 225 | [[package]] 226 | name = "actix-utils" 227 | version = "3.0.1" 228 | source = "registry+https://github.com/rust-lang/crates.io-index" 229 | checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8" 230 | dependencies = [ 231 | "local-waker", 232 | "pin-project-lite", 233 | ] 234 | 235 | [[package]] 236 | name = "actix-web" 237 | version = "4.9.0" 238 | source = "registry+https://github.com/rust-lang/crates.io-index" 239 | checksum = "9180d76e5cc7ccbc4d60a506f2c727730b154010262df5b910eb17dbe4b8cb38" 240 | dependencies = [ 241 | "actix-codec", 242 | "actix-http", 243 | "actix-macros", 244 | "actix-router", 245 | "actix-rt", 246 | "actix-server", 247 | "actix-service", 248 | "actix-utils", 249 | "actix-web-codegen", 250 | "ahash 0.8.11", 251 | "bytes", 252 | "bytestring", 253 | "cfg-if", 254 | "cookie", 255 | "derive_more", 256 | "encoding_rs", 257 | "futures-core", 258 | "futures-util", 259 | "impl-more", 260 | "itoa", 261 | "language-tags", 262 | "log", 263 | "mime", 264 | "once_cell", 265 | "pin-project-lite", 266 | "regex", 267 | "regex-lite", 268 | "serde", 269 | "serde_json", 270 | "serde_urlencoded", 271 | "smallvec", 272 | "socket2", 273 | "time", 274 | "url", 275 | ] 276 | 277 | [[package]] 278 | name = "actix-web-actors" 279 | version = "4.3.1+deprecated" 280 | source = "registry+https://github.com/rust-lang/crates.io-index" 281 | checksum = "f98c5300b38fd004fe7d2a964f9a90813fdbe8a81fed500587e78b1b71c6f980" 282 | dependencies = [ 283 | "actix", 284 | "actix-codec", 285 | "actix-http", 286 | "actix-web", 287 | "bytes", 288 | "bytestring", 289 | "futures-core", 290 | "pin-project-lite", 291 | "tokio", 292 | "tokio-util", 293 | ] 294 | 295 | [[package]] 296 | name = "actix-web-codegen" 297 | version = "4.3.0" 298 | source = "registry+https://github.com/rust-lang/crates.io-index" 299 | checksum = "f591380e2e68490b5dfaf1dd1aa0ebe78d84ba7067078512b4ea6e4492d622b8" 300 | dependencies = [ 301 | "actix-router", 302 | "proc-macro2", 303 | "quote", 304 | "syn 2.0.89", 305 | ] 306 | 307 | [[package]] 308 | name = "actix_derive" 309 | version = "0.6.2" 310 | source = "registry+https://github.com/rust-lang/crates.io-index" 311 | checksum = "b6ac1e58cded18cb28ddc17143c4dea5345b3ad575e14f32f66e4054a56eb271" 312 | dependencies = [ 313 | "proc-macro2", 314 | "quote", 315 | "syn 2.0.89", 316 | ] 317 | 318 | [[package]] 319 | name = "addr2line" 320 | version = "0.24.2" 321 | source = "registry+https://github.com/rust-lang/crates.io-index" 322 | checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" 323 | dependencies = [ 324 | "gimli", 325 | ] 326 | 327 | [[package]] 328 | name = "adler2" 329 | version = "2.0.0" 330 | source = "registry+https://github.com/rust-lang/crates.io-index" 331 | checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" 332 | 333 | [[package]] 334 | name = "ahash" 335 | version = "0.7.8" 336 | source = "registry+https://github.com/rust-lang/crates.io-index" 337 | checksum = "891477e0c6a8957309ee5c45a6368af3ae14bb510732d2684ffa19af310920f9" 338 | dependencies = [ 339 | "getrandom", 340 | "once_cell", 341 | "version_check", 342 | ] 343 | 344 | [[package]] 345 | name = "ahash" 346 | version = "0.8.11" 347 | source = "registry+https://github.com/rust-lang/crates.io-index" 348 | checksum = "e89da841a80418a9b391ebaea17f5c112ffaaa96f621d2c285b5174da76b9011" 349 | dependencies = [ 350 | "cfg-if", 351 | "getrandom", 352 | "once_cell", 353 | "version_check", 354 | "zerocopy", 355 | ] 356 | 357 | [[package]] 358 | name = "aho-corasick" 359 | version = "1.1.3" 360 | source = "registry+https://github.com/rust-lang/crates.io-index" 361 | checksum = "8e60d3430d3a69478ad0993f19238d2df97c507009a52b3c10addcd7f6bcb916" 362 | dependencies = [ 363 | "memchr", 364 | ] 365 | 366 | [[package]] 367 | name = "aligned-vec" 368 | version = "0.5.0" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "4aa90d7ce82d4be67b64039a3d588d38dbcc6736577de4a847025ce5b0c468d1" 371 | 372 | [[package]] 373 | name = "alloc-no-stdlib" 374 | version = "2.0.4" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "cc7bb162ec39d46ab1ca8c77bf72e890535becd1751bb45f64c597edb4c8c6b3" 377 | 378 | [[package]] 379 | name = "alloc-stdlib" 380 | version = "0.2.2" 381 | source = "registry+https://github.com/rust-lang/crates.io-index" 382 | checksum = "94fb8275041c72129eb51b7d0322c29b8387a0386127718b096429201a5d6ece" 383 | dependencies = [ 384 | "alloc-no-stdlib", 385 | ] 386 | 387 | [[package]] 388 | name = "allocator-api2" 389 | version = "0.2.20" 390 | source = "registry+https://github.com/rust-lang/crates.io-index" 391 | checksum = "45862d1c77f2228b9e10bc609d5bc203d86ebc9b87ad8d5d5167a6c9abf739d9" 392 | 393 | [[package]] 394 | name = "android-tzdata" 395 | version = "0.1.1" 396 | source = "registry+https://github.com/rust-lang/crates.io-index" 397 | checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" 398 | 399 | [[package]] 400 | name = "android_system_properties" 401 | version = "0.1.5" 402 | source = "registry+https://github.com/rust-lang/crates.io-index" 403 | checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 404 | dependencies = [ 405 | "libc", 406 | ] 407 | 408 | [[package]] 409 | name = "anstream" 410 | version = "0.6.18" 411 | source = "registry+https://github.com/rust-lang/crates.io-index" 412 | checksum = "8acc5369981196006228e28809f761875c0327210a891e941f4c683b3a99529b" 413 | dependencies = [ 414 | "anstyle", 415 | "anstyle-parse", 416 | "anstyle-query", 417 | "anstyle-wincon", 418 | "colorchoice", 419 | "is_terminal_polyfill", 420 | "utf8parse", 421 | ] 422 | 423 | [[package]] 424 | name = "anstyle" 425 | version = "1.0.10" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "55cc3b69f167a1ef2e161439aa98aed94e6028e5f9a59be9a6ffb47aef1651f9" 428 | 429 | [[package]] 430 | name = "anstyle-parse" 431 | version = "0.2.6" 432 | source = "registry+https://github.com/rust-lang/crates.io-index" 433 | checksum = "3b2d16507662817a6a20a9ea92df6652ee4f94f914589377d69f3b21bc5798a9" 434 | dependencies = [ 435 | "utf8parse", 436 | ] 437 | 438 | [[package]] 439 | name = "anstyle-query" 440 | version = "1.1.2" 441 | source = "registry+https://github.com/rust-lang/crates.io-index" 442 | checksum = "79947af37f4177cfead1110013d678905c37501914fba0efea834c3fe9a8d60c" 443 | dependencies = [ 444 | "windows-sys 0.59.0", 445 | ] 446 | 447 | [[package]] 448 | name = "anstyle-wincon" 449 | version = "3.0.6" 450 | source = "registry+https://github.com/rust-lang/crates.io-index" 451 | checksum = "2109dbce0e72be3ec00bed26e6a7479ca384ad226efdd66db8fa2e3a38c83125" 452 | dependencies = [ 453 | "anstyle", 454 | "windows-sys 0.59.0", 455 | ] 456 | 457 | [[package]] 458 | name = "anyhow" 459 | version = "1.0.93" 460 | source = "registry+https://github.com/rust-lang/crates.io-index" 461 | checksum = "4c95c10ba0b00a02636238b814946408b1322d5ac4760326e6fb8ec956d85775" 462 | 463 | [[package]] 464 | name = "arbitrary" 465 | version = "1.4.1" 466 | source = "registry+https://github.com/rust-lang/crates.io-index" 467 | checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223" 468 | dependencies = [ 469 | "derive_arbitrary", 470 | ] 471 | 472 | [[package]] 473 | name = "arg_enum_proc_macro" 474 | version = "0.3.4" 475 | source = "registry+https://github.com/rust-lang/crates.io-index" 476 | checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" 477 | dependencies = [ 478 | "proc-macro2", 479 | "quote", 480 | "syn 2.0.89", 481 | ] 482 | 483 | [[package]] 484 | name = "arrayvec" 485 | version = "0.7.6" 486 | source = "registry+https://github.com/rust-lang/crates.io-index" 487 | checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" 488 | 489 | [[package]] 490 | name = "atoi" 491 | version = "2.0.0" 492 | source = "registry+https://github.com/rust-lang/crates.io-index" 493 | checksum = "f28d99ec8bfea296261ca1af174f24225171fea9664ba9003cbebee704810528" 494 | dependencies = [ 495 | "num-traits", 496 | ] 497 | 498 | [[package]] 499 | name = "autocfg" 500 | version = "1.4.0" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 503 | 504 | [[package]] 505 | name = "av1-grain" 506 | version = "0.2.3" 507 | source = "registry+https://github.com/rust-lang/crates.io-index" 508 | checksum = "6678909d8c5d46a42abcf571271e15fdbc0a225e3646cf23762cd415046c78bf" 509 | dependencies = [ 510 | "anyhow", 511 | "arrayvec", 512 | "log", 513 | "nom", 514 | "num-rational", 515 | "v_frame", 516 | ] 517 | 518 | [[package]] 519 | name = "avif-serialize" 520 | version = "0.8.2" 521 | source = "registry+https://github.com/rust-lang/crates.io-index" 522 | checksum = "e335041290c43101ca215eed6f43ec437eb5a42125573f600fc3fa42b9bddd62" 523 | dependencies = [ 524 | "arrayvec", 525 | ] 526 | 527 | [[package]] 528 | name = "backtrace" 529 | version = "0.3.74" 530 | source = "registry+https://github.com/rust-lang/crates.io-index" 531 | checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" 532 | dependencies = [ 533 | "addr2line", 534 | "cfg-if", 535 | "libc", 536 | "miniz_oxide", 537 | "object", 538 | "rustc-demangle", 539 | "windows-targets 0.52.6", 540 | ] 541 | 542 | [[package]] 543 | name = "base64" 544 | version = "0.21.7" 545 | source = "registry+https://github.com/rust-lang/crates.io-index" 546 | checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" 547 | 548 | [[package]] 549 | name = "base64" 550 | version = "0.22.1" 551 | source = "registry+https://github.com/rust-lang/crates.io-index" 552 | checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 553 | 554 | [[package]] 555 | name = "base64ct" 556 | version = "1.6.0" 557 | source = "registry+https://github.com/rust-lang/crates.io-index" 558 | checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" 559 | 560 | [[package]] 561 | name = "bit_field" 562 | version = "0.10.2" 563 | source = "registry+https://github.com/rust-lang/crates.io-index" 564 | checksum = "dc827186963e592360843fb5ba4b973e145841266c1357f7180c43526f2e5b61" 565 | 566 | [[package]] 567 | name = "bitflags" 568 | version = "1.3.2" 569 | source = "registry+https://github.com/rust-lang/crates.io-index" 570 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 571 | 572 | [[package]] 573 | name = "bitflags" 574 | version = "2.6.0" 575 | source = "registry+https://github.com/rust-lang/crates.io-index" 576 | checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" 577 | dependencies = [ 578 | "serde", 579 | ] 580 | 581 | [[package]] 582 | name = "bitstream-io" 583 | version = "2.6.0" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "6099cdc01846bc367c4e7dd630dc5966dccf36b652fae7a74e17b640411a91b2" 586 | 587 | [[package]] 588 | name = "bitvec" 589 | version = "1.0.1" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c" 592 | dependencies = [ 593 | "funty", 594 | "radium", 595 | "tap", 596 | "wyz", 597 | ] 598 | 599 | [[package]] 600 | name = "block-buffer" 601 | version = "0.10.4" 602 | source = "registry+https://github.com/rust-lang/crates.io-index" 603 | checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" 604 | dependencies = [ 605 | "generic-array", 606 | ] 607 | 608 | [[package]] 609 | name = "borsh" 610 | version = "1.5.3" 611 | source = "registry+https://github.com/rust-lang/crates.io-index" 612 | checksum = "2506947f73ad44e344215ccd6403ac2ae18cd8e046e581a441bf8d199f257f03" 613 | dependencies = [ 614 | "borsh-derive", 615 | "cfg_aliases", 616 | ] 617 | 618 | [[package]] 619 | name = "borsh-derive" 620 | version = "1.5.3" 621 | source = "registry+https://github.com/rust-lang/crates.io-index" 622 | checksum = "c2593a3b8b938bd68373196c9832f516be11fa487ef4ae745eb282e6a56a7244" 623 | dependencies = [ 624 | "once_cell", 625 | "proc-macro-crate", 626 | "proc-macro2", 627 | "quote", 628 | "syn 2.0.89", 629 | ] 630 | 631 | [[package]] 632 | name = "brotli" 633 | version = "6.0.0" 634 | source = "registry+https://github.com/rust-lang/crates.io-index" 635 | checksum = "74f7971dbd9326d58187408ab83117d8ac1bb9c17b085fdacd1cf2f598719b6b" 636 | dependencies = [ 637 | "alloc-no-stdlib", 638 | "alloc-stdlib", 639 | "brotli-decompressor", 640 | ] 641 | 642 | [[package]] 643 | name = "brotli-decompressor" 644 | version = "4.0.1" 645 | source = "registry+https://github.com/rust-lang/crates.io-index" 646 | checksum = "9a45bd2e4095a8b518033b128020dd4a55aab1c0a381ba4404a472630f4bc362" 647 | dependencies = [ 648 | "alloc-no-stdlib", 649 | "alloc-stdlib", 650 | ] 651 | 652 | [[package]] 653 | name = "built" 654 | version = "0.7.5" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "c360505aed52b7ec96a3636c3f039d99103c37d1d9b4f7a8c743d3ea9ffcd03b" 657 | 658 | [[package]] 659 | name = "bumpalo" 660 | version = "3.16.0" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" 663 | 664 | [[package]] 665 | name = "bytecheck" 666 | version = "0.6.12" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" 669 | dependencies = [ 670 | "bytecheck_derive", 671 | "ptr_meta", 672 | "simdutf8", 673 | ] 674 | 675 | [[package]] 676 | name = "bytecheck_derive" 677 | version = "0.6.12" 678 | source = "registry+https://github.com/rust-lang/crates.io-index" 679 | checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" 680 | dependencies = [ 681 | "proc-macro2", 682 | "quote", 683 | "syn 1.0.109", 684 | ] 685 | 686 | [[package]] 687 | name = "bytemuck" 688 | version = "1.20.0" 689 | source = "registry+https://github.com/rust-lang/crates.io-index" 690 | checksum = "8b37c88a63ffd85d15b406896cc343916d7cf57838a847b3a6f2ca5d39a5695a" 691 | 692 | [[package]] 693 | name = "byteorder" 694 | version = "1.5.0" 695 | source = "registry+https://github.com/rust-lang/crates.io-index" 696 | checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" 697 | 698 | [[package]] 699 | name = "byteorder-lite" 700 | version = "0.1.0" 701 | source = "registry+https://github.com/rust-lang/crates.io-index" 702 | checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" 703 | 704 | [[package]] 705 | name = "bytes" 706 | version = "1.8.0" 707 | source = "registry+https://github.com/rust-lang/crates.io-index" 708 | checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" 709 | 710 | [[package]] 711 | name = "bytestring" 712 | version = "1.4.0" 713 | source = "registry+https://github.com/rust-lang/crates.io-index" 714 | checksum = "e465647ae23b2823b0753f50decb2d5a86d2bb2cac04788fafd1f80e45378e5f" 715 | dependencies = [ 716 | "bytes", 717 | ] 718 | 719 | [[package]] 720 | name = "cc" 721 | version = "1.2.1" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47" 724 | dependencies = [ 725 | "jobserver", 726 | "libc", 727 | "shlex", 728 | ] 729 | 730 | [[package]] 731 | name = "cfg-expr" 732 | version = "0.15.8" 733 | source = "registry+https://github.com/rust-lang/crates.io-index" 734 | checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" 735 | dependencies = [ 736 | "smallvec", 737 | "target-lexicon", 738 | ] 739 | 740 | [[package]] 741 | name = "cfg-if" 742 | version = "1.0.0" 743 | source = "registry+https://github.com/rust-lang/crates.io-index" 744 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 745 | 746 | [[package]] 747 | name = "cfg_aliases" 748 | version = "0.2.1" 749 | source = "registry+https://github.com/rust-lang/crates.io-index" 750 | checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" 751 | 752 | [[package]] 753 | name = "chrono" 754 | version = "0.4.38" 755 | source = "registry+https://github.com/rust-lang/crates.io-index" 756 | checksum = "a21f936df1771bf62b77f047b726c4625ff2e8aa607c01ec06e5a05bd8463401" 757 | dependencies = [ 758 | "android-tzdata", 759 | "iana-time-zone", 760 | "js-sys", 761 | "num-traits", 762 | "serde", 763 | "wasm-bindgen", 764 | "windows-targets 0.52.6", 765 | ] 766 | 767 | [[package]] 768 | name = "clap" 769 | version = "4.5.21" 770 | source = "registry+https://github.com/rust-lang/crates.io-index" 771 | checksum = "fb3b4b9e5a7c7514dfa52869339ee98b3156b0bfb4e8a77c4ff4babb64b1604f" 772 | dependencies = [ 773 | "clap_builder", 774 | "clap_derive", 775 | ] 776 | 777 | [[package]] 778 | name = "clap_builder" 779 | version = "4.5.21" 780 | source = "registry+https://github.com/rust-lang/crates.io-index" 781 | checksum = "b17a95aa67cc7b5ebd32aa5370189aa0d79069ef1c64ce893bd30fb24bff20ec" 782 | dependencies = [ 783 | "anstream", 784 | "anstyle", 785 | "clap_lex", 786 | "strsim", 787 | ] 788 | 789 | [[package]] 790 | name = "clap_derive" 791 | version = "4.5.18" 792 | source = "registry+https://github.com/rust-lang/crates.io-index" 793 | checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" 794 | dependencies = [ 795 | "heck", 796 | "proc-macro2", 797 | "quote", 798 | "syn 2.0.89", 799 | ] 800 | 801 | [[package]] 802 | name = "clap_lex" 803 | version = "0.7.3" 804 | source = "registry+https://github.com/rust-lang/crates.io-index" 805 | checksum = "afb84c814227b90d6895e01398aee0d8033c00e7466aca416fb6a8e0eb19d8a7" 806 | 807 | [[package]] 808 | name = "color_quant" 809 | version = "1.1.0" 810 | source = "registry+https://github.com/rust-lang/crates.io-index" 811 | checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" 812 | 813 | [[package]] 814 | name = "colorchoice" 815 | version = "1.0.3" 816 | source = "registry+https://github.com/rust-lang/crates.io-index" 817 | checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" 818 | 819 | [[package]] 820 | name = "concurrent-queue" 821 | version = "2.5.0" 822 | source = "registry+https://github.com/rust-lang/crates.io-index" 823 | checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" 824 | dependencies = [ 825 | "crossbeam-utils", 826 | ] 827 | 828 | [[package]] 829 | name = "const-oid" 830 | version = "0.9.6" 831 | source = "registry+https://github.com/rust-lang/crates.io-index" 832 | checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8" 833 | 834 | [[package]] 835 | name = "convert_case" 836 | version = "0.4.0" 837 | source = "registry+https://github.com/rust-lang/crates.io-index" 838 | checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" 839 | 840 | [[package]] 841 | name = "cookie" 842 | version = "0.16.2" 843 | source = "registry+https://github.com/rust-lang/crates.io-index" 844 | checksum = "e859cd57d0710d9e06c381b550c06e76992472a8c6d527aecd2fc673dcc231fb" 845 | dependencies = [ 846 | "percent-encoding", 847 | "time", 848 | "version_check", 849 | ] 850 | 851 | [[package]] 852 | name = "core-foundation-sys" 853 | version = "0.8.7" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 856 | 857 | [[package]] 858 | name = "cpufeatures" 859 | version = "0.2.16" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" 862 | dependencies = [ 863 | "libc", 864 | ] 865 | 866 | [[package]] 867 | name = "crc" 868 | version = "3.2.1" 869 | source = "registry+https://github.com/rust-lang/crates.io-index" 870 | checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636" 871 | dependencies = [ 872 | "crc-catalog", 873 | ] 874 | 875 | [[package]] 876 | name = "crc-catalog" 877 | version = "2.4.0" 878 | source = "registry+https://github.com/rust-lang/crates.io-index" 879 | checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5" 880 | 881 | [[package]] 882 | name = "crc32fast" 883 | version = "1.4.2" 884 | source = "registry+https://github.com/rust-lang/crates.io-index" 885 | checksum = "a97769d94ddab943e4510d138150169a2758b5ef3eb191a9ee688de3e23ef7b3" 886 | dependencies = [ 887 | "cfg-if", 888 | ] 889 | 890 | [[package]] 891 | name = "crossbeam-channel" 892 | version = "0.5.13" 893 | source = "registry+https://github.com/rust-lang/crates.io-index" 894 | checksum = "33480d6946193aa8033910124896ca395333cae7e2d1113d1fef6c3272217df2" 895 | dependencies = [ 896 | "crossbeam-utils", 897 | ] 898 | 899 | [[package]] 900 | name = "crossbeam-deque" 901 | version = "0.8.5" 902 | source = "registry+https://github.com/rust-lang/crates.io-index" 903 | checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" 904 | dependencies = [ 905 | "crossbeam-epoch", 906 | "crossbeam-utils", 907 | ] 908 | 909 | [[package]] 910 | name = "crossbeam-epoch" 911 | version = "0.9.18" 912 | source = "registry+https://github.com/rust-lang/crates.io-index" 913 | checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" 914 | dependencies = [ 915 | "crossbeam-utils", 916 | ] 917 | 918 | [[package]] 919 | name = "crossbeam-queue" 920 | version = "0.3.11" 921 | source = "registry+https://github.com/rust-lang/crates.io-index" 922 | checksum = "df0346b5d5e76ac2fe4e327c5fd1118d6be7c51dfb18f9b7922923f287471e35" 923 | dependencies = [ 924 | "crossbeam-utils", 925 | ] 926 | 927 | [[package]] 928 | name = "crossbeam-utils" 929 | version = "0.8.20" 930 | source = "registry+https://github.com/rust-lang/crates.io-index" 931 | checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" 932 | 933 | [[package]] 934 | name = "crunchy" 935 | version = "0.2.2" 936 | source = "registry+https://github.com/rust-lang/crates.io-index" 937 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 938 | 939 | [[package]] 940 | name = "crypto-common" 941 | version = "0.1.6" 942 | source = "registry+https://github.com/rust-lang/crates.io-index" 943 | checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" 944 | dependencies = [ 945 | "generic-array", 946 | "typenum", 947 | ] 948 | 949 | [[package]] 950 | name = "darling" 951 | version = "0.20.10" 952 | source = "registry+https://github.com/rust-lang/crates.io-index" 953 | checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" 954 | dependencies = [ 955 | "darling_core", 956 | "darling_macro", 957 | ] 958 | 959 | [[package]] 960 | name = "darling_core" 961 | version = "0.20.10" 962 | source = "registry+https://github.com/rust-lang/crates.io-index" 963 | checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" 964 | dependencies = [ 965 | "fnv", 966 | "ident_case", 967 | "proc-macro2", 968 | "quote", 969 | "strsim", 970 | "syn 2.0.89", 971 | ] 972 | 973 | [[package]] 974 | name = "darling_macro" 975 | version = "0.20.10" 976 | source = "registry+https://github.com/rust-lang/crates.io-index" 977 | checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" 978 | dependencies = [ 979 | "darling_core", 980 | "quote", 981 | "syn 2.0.89", 982 | ] 983 | 984 | [[package]] 985 | name = "der" 986 | version = "0.7.9" 987 | source = "registry+https://github.com/rust-lang/crates.io-index" 988 | checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" 989 | dependencies = [ 990 | "const-oid", 991 | "pem-rfc7468", 992 | "zeroize", 993 | ] 994 | 995 | [[package]] 996 | name = "deranged" 997 | version = "0.3.11" 998 | source = "registry+https://github.com/rust-lang/crates.io-index" 999 | checksum = "b42b6fa04a440b495c8b04d0e71b707c585f83cb9cb28cf8cd0d976c315e31b4" 1000 | dependencies = [ 1001 | "powerfmt", 1002 | ] 1003 | 1004 | [[package]] 1005 | name = "derive_arbitrary" 1006 | version = "1.4.1" 1007 | source = "registry+https://github.com/rust-lang/crates.io-index" 1008 | checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800" 1009 | dependencies = [ 1010 | "proc-macro2", 1011 | "quote", 1012 | "syn 2.0.89", 1013 | ] 1014 | 1015 | [[package]] 1016 | name = "derive_more" 1017 | version = "0.99.18" 1018 | source = "registry+https://github.com/rust-lang/crates.io-index" 1019 | checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" 1020 | dependencies = [ 1021 | "convert_case", 1022 | "proc-macro2", 1023 | "quote", 1024 | "rustc_version", 1025 | "syn 2.0.89", 1026 | ] 1027 | 1028 | [[package]] 1029 | name = "digest" 1030 | version = "0.10.7" 1031 | source = "registry+https://github.com/rust-lang/crates.io-index" 1032 | checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" 1033 | dependencies = [ 1034 | "block-buffer", 1035 | "const-oid", 1036 | "crypto-common", 1037 | "subtle", 1038 | ] 1039 | 1040 | [[package]] 1041 | name = "displaydoc" 1042 | version = "0.2.5" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "97369cbbc041bc366949bc74d34658d6cda5621039731c6310521892a3a20ae0" 1045 | dependencies = [ 1046 | "proc-macro2", 1047 | "quote", 1048 | "syn 2.0.89", 1049 | ] 1050 | 1051 | [[package]] 1052 | name = "document-features" 1053 | version = "0.2.10" 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" 1055 | checksum = "cb6969eaabd2421f8a2775cfd2471a2b634372b4a25d41e3bd647b79912850a0" 1056 | dependencies = [ 1057 | "litrs", 1058 | ] 1059 | 1060 | [[package]] 1061 | name = "dotenv" 1062 | version = "0.15.0" 1063 | source = "registry+https://github.com/rust-lang/crates.io-index" 1064 | checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" 1065 | 1066 | [[package]] 1067 | name = "dotenvy" 1068 | version = "0.15.7" 1069 | source = "registry+https://github.com/rust-lang/crates.io-index" 1070 | checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" 1071 | 1072 | [[package]] 1073 | name = "either" 1074 | version = "1.13.0" 1075 | source = "registry+https://github.com/rust-lang/crates.io-index" 1076 | checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" 1077 | dependencies = [ 1078 | "serde", 1079 | ] 1080 | 1081 | [[package]] 1082 | name = "encoding_rs" 1083 | version = "0.8.35" 1084 | source = "registry+https://github.com/rust-lang/crates.io-index" 1085 | checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3" 1086 | dependencies = [ 1087 | "cfg-if", 1088 | ] 1089 | 1090 | [[package]] 1091 | name = "equivalent" 1092 | version = "1.0.1" 1093 | source = "registry+https://github.com/rust-lang/crates.io-index" 1094 | checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" 1095 | 1096 | [[package]] 1097 | name = "errno" 1098 | version = "0.3.9" 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" 1100 | checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" 1101 | dependencies = [ 1102 | "libc", 1103 | "windows-sys 0.52.0", 1104 | ] 1105 | 1106 | [[package]] 1107 | name = "etcetera" 1108 | version = "0.8.0" 1109 | source = "registry+https://github.com/rust-lang/crates.io-index" 1110 | checksum = "136d1b5283a1ab77bd9257427ffd09d8667ced0570b6f938942bc7568ed5b943" 1111 | dependencies = [ 1112 | "cfg-if", 1113 | "home", 1114 | "windows-sys 0.48.0", 1115 | ] 1116 | 1117 | [[package]] 1118 | name = "event-listener" 1119 | version = "5.3.1" 1120 | source = "registry+https://github.com/rust-lang/crates.io-index" 1121 | checksum = "6032be9bd27023a771701cc49f9f053c751055f71efb2e0ae5c15809093675ba" 1122 | dependencies = [ 1123 | "concurrent-queue", 1124 | "parking", 1125 | "pin-project-lite", 1126 | ] 1127 | 1128 | [[package]] 1129 | name = "exr" 1130 | version = "1.73.0" 1131 | source = "registry+https://github.com/rust-lang/crates.io-index" 1132 | checksum = "f83197f59927b46c04a183a619b7c29df34e63e63c7869320862268c0ef687e0" 1133 | dependencies = [ 1134 | "bit_field", 1135 | "half", 1136 | "lebe", 1137 | "miniz_oxide", 1138 | "rayon-core", 1139 | "smallvec", 1140 | "zune-inflate", 1141 | ] 1142 | 1143 | [[package]] 1144 | name = "fast_image_resize" 1145 | version = "5.0.0" 1146 | source = "registry+https://github.com/rust-lang/crates.io-index" 1147 | checksum = "a66a61fbfc84ef99a839499cf9e5a7c2951d2da874ea00f29ee938bc50d1b396" 1148 | dependencies = [ 1149 | "cfg-if", 1150 | "document-features", 1151 | "num-traits", 1152 | "thiserror 1.0.69", 1153 | ] 1154 | 1155 | [[package]] 1156 | name = "fastrand" 1157 | version = "2.2.0" 1158 | source = "registry+https://github.com/rust-lang/crates.io-index" 1159 | checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4" 1160 | 1161 | [[package]] 1162 | name = "fdeflate" 1163 | version = "0.3.6" 1164 | source = "registry+https://github.com/rust-lang/crates.io-index" 1165 | checksum = "07c6f4c64c1d33a3111c4466f7365ebdcc37c5bd1ea0d62aae2e3d722aacbedb" 1166 | dependencies = [ 1167 | "simd-adler32", 1168 | ] 1169 | 1170 | [[package]] 1171 | name = "flate2" 1172 | version = "1.0.35" 1173 | source = "registry+https://github.com/rust-lang/crates.io-index" 1174 | checksum = "c936bfdafb507ebbf50b8074c54fa31c5be9a1e7e5f467dd659697041407d07c" 1175 | dependencies = [ 1176 | "crc32fast", 1177 | "miniz_oxide", 1178 | ] 1179 | 1180 | [[package]] 1181 | name = "flume" 1182 | version = "0.11.1" 1183 | source = "registry+https://github.com/rust-lang/crates.io-index" 1184 | checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" 1185 | dependencies = [ 1186 | "futures-core", 1187 | "futures-sink", 1188 | "spin", 1189 | ] 1190 | 1191 | [[package]] 1192 | name = "fnv" 1193 | version = "1.0.7" 1194 | source = "registry+https://github.com/rust-lang/crates.io-index" 1195 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 1196 | 1197 | [[package]] 1198 | name = "form_urlencoded" 1199 | version = "1.2.1" 1200 | source = "registry+https://github.com/rust-lang/crates.io-index" 1201 | checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" 1202 | dependencies = [ 1203 | "percent-encoding", 1204 | ] 1205 | 1206 | [[package]] 1207 | name = "funty" 1208 | version = "2.0.0" 1209 | source = "registry+https://github.com/rust-lang/crates.io-index" 1210 | checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" 1211 | 1212 | [[package]] 1213 | name = "futures-channel" 1214 | version = "0.3.31" 1215 | source = "registry+https://github.com/rust-lang/crates.io-index" 1216 | checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 1217 | dependencies = [ 1218 | "futures-core", 1219 | "futures-sink", 1220 | ] 1221 | 1222 | [[package]] 1223 | name = "futures-core" 1224 | version = "0.3.31" 1225 | source = "registry+https://github.com/rust-lang/crates.io-index" 1226 | checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 1227 | 1228 | [[package]] 1229 | name = "futures-executor" 1230 | version = "0.3.31" 1231 | source = "registry+https://github.com/rust-lang/crates.io-index" 1232 | checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 1233 | dependencies = [ 1234 | "futures-core", 1235 | "futures-task", 1236 | "futures-util", 1237 | ] 1238 | 1239 | [[package]] 1240 | name = "futures-intrusive" 1241 | version = "0.5.0" 1242 | source = "registry+https://github.com/rust-lang/crates.io-index" 1243 | checksum = "1d930c203dd0b6ff06e0201a4a2fe9149b43c684fd4420555b26d21b1a02956f" 1244 | dependencies = [ 1245 | "futures-core", 1246 | "lock_api", 1247 | "parking_lot", 1248 | ] 1249 | 1250 | [[package]] 1251 | name = "futures-io" 1252 | version = "0.3.31" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "9e5c1b78ca4aae1ac06c48a526a655760685149f0d465d21f37abfe57ce075c6" 1255 | 1256 | [[package]] 1257 | name = "futures-sink" 1258 | version = "0.3.31" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 1261 | 1262 | [[package]] 1263 | name = "futures-task" 1264 | version = "0.3.31" 1265 | source = "registry+https://github.com/rust-lang/crates.io-index" 1266 | checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 1267 | 1268 | [[package]] 1269 | name = "futures-util" 1270 | version = "0.3.31" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 1273 | dependencies = [ 1274 | "futures-core", 1275 | "futures-io", 1276 | "futures-sink", 1277 | "futures-task", 1278 | "memchr", 1279 | "pin-project-lite", 1280 | "pin-utils", 1281 | "slab", 1282 | ] 1283 | 1284 | [[package]] 1285 | name = "generic-array" 1286 | version = "0.14.7" 1287 | source = "registry+https://github.com/rust-lang/crates.io-index" 1288 | checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" 1289 | dependencies = [ 1290 | "typenum", 1291 | "version_check", 1292 | ] 1293 | 1294 | [[package]] 1295 | name = "getrandom" 1296 | version = "0.2.15" 1297 | source = "registry+https://github.com/rust-lang/crates.io-index" 1298 | checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7" 1299 | dependencies = [ 1300 | "cfg-if", 1301 | "js-sys", 1302 | "libc", 1303 | "wasi", 1304 | "wasm-bindgen", 1305 | ] 1306 | 1307 | [[package]] 1308 | name = "gif" 1309 | version = "0.13.1" 1310 | source = "registry+https://github.com/rust-lang/crates.io-index" 1311 | checksum = "3fb2d69b19215e18bb912fa30f7ce15846e301408695e44e0ef719f1da9e19f2" 1312 | dependencies = [ 1313 | "color_quant", 1314 | "weezl", 1315 | ] 1316 | 1317 | [[package]] 1318 | name = "gimli" 1319 | version = "0.31.1" 1320 | source = "registry+https://github.com/rust-lang/crates.io-index" 1321 | checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" 1322 | 1323 | [[package]] 1324 | name = "h2" 1325 | version = "0.3.26" 1326 | source = "registry+https://github.com/rust-lang/crates.io-index" 1327 | checksum = "81fe527a889e1532da5c525686d96d4c2e74cdd345badf8dfef9f6b39dd5f5e8" 1328 | dependencies = [ 1329 | "bytes", 1330 | "fnv", 1331 | "futures-core", 1332 | "futures-sink", 1333 | "futures-util", 1334 | "http", 1335 | "indexmap", 1336 | "slab", 1337 | "tokio", 1338 | "tokio-util", 1339 | "tracing", 1340 | ] 1341 | 1342 | [[package]] 1343 | name = "half" 1344 | version = "2.4.1" 1345 | source = "registry+https://github.com/rust-lang/crates.io-index" 1346 | checksum = "6dd08c532ae367adf81c312a4580bc67f1d0fe8bc9c460520283f4c0ff277888" 1347 | dependencies = [ 1348 | "cfg-if", 1349 | "crunchy", 1350 | ] 1351 | 1352 | [[package]] 1353 | name = "hashbrown" 1354 | version = "0.12.3" 1355 | source = "registry+https://github.com/rust-lang/crates.io-index" 1356 | checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 1357 | dependencies = [ 1358 | "ahash 0.7.8", 1359 | ] 1360 | 1361 | [[package]] 1362 | name = "hashbrown" 1363 | version = "0.14.5" 1364 | source = "registry+https://github.com/rust-lang/crates.io-index" 1365 | checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" 1366 | dependencies = [ 1367 | "ahash 0.8.11", 1368 | "allocator-api2", 1369 | ] 1370 | 1371 | [[package]] 1372 | name = "hashbrown" 1373 | version = "0.15.2" 1374 | source = "registry+https://github.com/rust-lang/crates.io-index" 1375 | checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" 1376 | 1377 | [[package]] 1378 | name = "hashlink" 1379 | version = "0.9.1" 1380 | source = "registry+https://github.com/rust-lang/crates.io-index" 1381 | checksum = "6ba4ff7128dee98c7dc9794b6a411377e1404dba1c97deb8d1a55297bd25d8af" 1382 | dependencies = [ 1383 | "hashbrown 0.14.5", 1384 | ] 1385 | 1386 | [[package]] 1387 | name = "heck" 1388 | version = "0.5.0" 1389 | source = "registry+https://github.com/rust-lang/crates.io-index" 1390 | checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" 1391 | 1392 | [[package]] 1393 | name = "hermit-abi" 1394 | version = "0.3.9" 1395 | source = "registry+https://github.com/rust-lang/crates.io-index" 1396 | checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024" 1397 | 1398 | [[package]] 1399 | name = "hex" 1400 | version = "0.4.3" 1401 | source = "registry+https://github.com/rust-lang/crates.io-index" 1402 | checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" 1403 | 1404 | [[package]] 1405 | name = "hkdf" 1406 | version = "0.12.4" 1407 | source = "registry+https://github.com/rust-lang/crates.io-index" 1408 | checksum = "7b5f8eb2ad728638ea2c7d47a21db23b7b58a72ed6a38256b8a1849f15fbbdf7" 1409 | dependencies = [ 1410 | "hmac", 1411 | ] 1412 | 1413 | [[package]] 1414 | name = "hmac" 1415 | version = "0.12.1" 1416 | source = "registry+https://github.com/rust-lang/crates.io-index" 1417 | checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" 1418 | dependencies = [ 1419 | "digest", 1420 | ] 1421 | 1422 | [[package]] 1423 | name = "home" 1424 | version = "0.5.9" 1425 | source = "registry+https://github.com/rust-lang/crates.io-index" 1426 | checksum = "e3d1354bf6b7235cb4a0576c2619fd4ed18183f689b12b006a0ee7329eeff9a5" 1427 | dependencies = [ 1428 | "windows-sys 0.52.0", 1429 | ] 1430 | 1431 | [[package]] 1432 | name = "http" 1433 | version = "0.2.12" 1434 | source = "registry+https://github.com/rust-lang/crates.io-index" 1435 | checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1" 1436 | dependencies = [ 1437 | "bytes", 1438 | "fnv", 1439 | "itoa", 1440 | ] 1441 | 1442 | [[package]] 1443 | name = "http-range" 1444 | version = "0.1.5" 1445 | source = "registry+https://github.com/rust-lang/crates.io-index" 1446 | checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" 1447 | 1448 | [[package]] 1449 | name = "httparse" 1450 | version = "1.9.5" 1451 | source = "registry+https://github.com/rust-lang/crates.io-index" 1452 | checksum = "7d71d3574edd2771538b901e6549113b4006ece66150fb69c0fb6d9a2adae946" 1453 | 1454 | [[package]] 1455 | name = "httpdate" 1456 | version = "1.0.3" 1457 | source = "registry+https://github.com/rust-lang/crates.io-index" 1458 | checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 1459 | 1460 | [[package]] 1461 | name = "iana-time-zone" 1462 | version = "0.1.61" 1463 | source = "registry+https://github.com/rust-lang/crates.io-index" 1464 | checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" 1465 | dependencies = [ 1466 | "android_system_properties", 1467 | "core-foundation-sys", 1468 | "iana-time-zone-haiku", 1469 | "js-sys", 1470 | "wasm-bindgen", 1471 | "windows-core", 1472 | ] 1473 | 1474 | [[package]] 1475 | name = "iana-time-zone-haiku" 1476 | version = "0.1.2" 1477 | source = "registry+https://github.com/rust-lang/crates.io-index" 1478 | checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 1479 | dependencies = [ 1480 | "cc", 1481 | ] 1482 | 1483 | [[package]] 1484 | name = "icu_collections" 1485 | version = "1.5.0" 1486 | source = "registry+https://github.com/rust-lang/crates.io-index" 1487 | checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" 1488 | dependencies = [ 1489 | "displaydoc", 1490 | "yoke", 1491 | "zerofrom", 1492 | "zerovec", 1493 | ] 1494 | 1495 | [[package]] 1496 | name = "icu_locid" 1497 | version = "1.5.0" 1498 | source = "registry+https://github.com/rust-lang/crates.io-index" 1499 | checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" 1500 | dependencies = [ 1501 | "displaydoc", 1502 | "litemap", 1503 | "tinystr", 1504 | "writeable", 1505 | "zerovec", 1506 | ] 1507 | 1508 | [[package]] 1509 | name = "icu_locid_transform" 1510 | version = "1.5.0" 1511 | source = "registry+https://github.com/rust-lang/crates.io-index" 1512 | checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" 1513 | dependencies = [ 1514 | "displaydoc", 1515 | "icu_locid", 1516 | "icu_locid_transform_data", 1517 | "icu_provider", 1518 | "tinystr", 1519 | "zerovec", 1520 | ] 1521 | 1522 | [[package]] 1523 | name = "icu_locid_transform_data" 1524 | version = "1.5.0" 1525 | source = "registry+https://github.com/rust-lang/crates.io-index" 1526 | checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" 1527 | 1528 | [[package]] 1529 | name = "icu_normalizer" 1530 | version = "1.5.0" 1531 | source = "registry+https://github.com/rust-lang/crates.io-index" 1532 | checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" 1533 | dependencies = [ 1534 | "displaydoc", 1535 | "icu_collections", 1536 | "icu_normalizer_data", 1537 | "icu_properties", 1538 | "icu_provider", 1539 | "smallvec", 1540 | "utf16_iter", 1541 | "utf8_iter", 1542 | "write16", 1543 | "zerovec", 1544 | ] 1545 | 1546 | [[package]] 1547 | name = "icu_normalizer_data" 1548 | version = "1.5.0" 1549 | source = "registry+https://github.com/rust-lang/crates.io-index" 1550 | checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" 1551 | 1552 | [[package]] 1553 | name = "icu_properties" 1554 | version = "1.5.1" 1555 | source = "registry+https://github.com/rust-lang/crates.io-index" 1556 | checksum = "93d6020766cfc6302c15dbbc9c8778c37e62c14427cb7f6e601d849e092aeef5" 1557 | dependencies = [ 1558 | "displaydoc", 1559 | "icu_collections", 1560 | "icu_locid_transform", 1561 | "icu_properties_data", 1562 | "icu_provider", 1563 | "tinystr", 1564 | "zerovec", 1565 | ] 1566 | 1567 | [[package]] 1568 | name = "icu_properties_data" 1569 | version = "1.5.0" 1570 | source = "registry+https://github.com/rust-lang/crates.io-index" 1571 | checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" 1572 | 1573 | [[package]] 1574 | name = "icu_provider" 1575 | version = "1.5.0" 1576 | source = "registry+https://github.com/rust-lang/crates.io-index" 1577 | checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" 1578 | dependencies = [ 1579 | "displaydoc", 1580 | "icu_locid", 1581 | "icu_provider_macros", 1582 | "stable_deref_trait", 1583 | "tinystr", 1584 | "writeable", 1585 | "yoke", 1586 | "zerofrom", 1587 | "zerovec", 1588 | ] 1589 | 1590 | [[package]] 1591 | name = "icu_provider_macros" 1592 | version = "1.5.0" 1593 | source = "registry+https://github.com/rust-lang/crates.io-index" 1594 | checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" 1595 | dependencies = [ 1596 | "proc-macro2", 1597 | "quote", 1598 | "syn 2.0.89", 1599 | ] 1600 | 1601 | [[package]] 1602 | name = "ident_case" 1603 | version = "1.0.1" 1604 | source = "registry+https://github.com/rust-lang/crates.io-index" 1605 | checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" 1606 | 1607 | [[package]] 1608 | name = "idna" 1609 | version = "1.0.3" 1610 | source = "registry+https://github.com/rust-lang/crates.io-index" 1611 | checksum = "686f825264d630750a544639377bae737628043f20d38bbc029e8f29ea968a7e" 1612 | dependencies = [ 1613 | "idna_adapter", 1614 | "smallvec", 1615 | "utf8_iter", 1616 | ] 1617 | 1618 | [[package]] 1619 | name = "idna_adapter" 1620 | version = "1.2.0" 1621 | source = "registry+https://github.com/rust-lang/crates.io-index" 1622 | checksum = "daca1df1c957320b2cf139ac61e7bd64fed304c5040df000a745aa1de3b4ef71" 1623 | dependencies = [ 1624 | "icu_normalizer", 1625 | "icu_properties", 1626 | ] 1627 | 1628 | [[package]] 1629 | name = "image" 1630 | version = "0.25.5" 1631 | source = "registry+https://github.com/rust-lang/crates.io-index" 1632 | checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" 1633 | dependencies = [ 1634 | "bytemuck", 1635 | "byteorder-lite", 1636 | "color_quant", 1637 | "exr", 1638 | "gif", 1639 | "image-webp", 1640 | "num-traits", 1641 | "png", 1642 | "qoi", 1643 | "ravif", 1644 | "rayon", 1645 | "rgb", 1646 | "tiff", 1647 | "zune-core", 1648 | "zune-jpeg", 1649 | ] 1650 | 1651 | [[package]] 1652 | name = "image-webp" 1653 | version = "0.2.0" 1654 | source = "registry+https://github.com/rust-lang/crates.io-index" 1655 | checksum = "e031e8e3d94711a9ccb5d6ea357439ef3dcbed361798bd4071dc4d9793fbe22f" 1656 | dependencies = [ 1657 | "byteorder-lite", 1658 | "quick-error", 1659 | ] 1660 | 1661 | [[package]] 1662 | name = "imgref" 1663 | version = "1.11.0" 1664 | source = "registry+https://github.com/rust-lang/crates.io-index" 1665 | checksum = "d0263a3d970d5c054ed9312c0057b4f3bde9c0b33836d3637361d4a9e6e7a408" 1666 | 1667 | [[package]] 1668 | name = "impl-more" 1669 | version = "0.1.8" 1670 | source = "registry+https://github.com/rust-lang/crates.io-index" 1671 | checksum = "aae21c3177a27788957044151cc2800043d127acaa460a47ebb9b84dfa2c6aa0" 1672 | 1673 | [[package]] 1674 | name = "indexmap" 1675 | version = "2.6.0" 1676 | source = "registry+https://github.com/rust-lang/crates.io-index" 1677 | checksum = "707907fe3c25f5424cce2cb7e1cbcafee6bdbe735ca90ef77c29e84591e5b9da" 1678 | dependencies = [ 1679 | "equivalent", 1680 | "hashbrown 0.15.2", 1681 | "serde", 1682 | ] 1683 | 1684 | [[package]] 1685 | name = "interpolate_name" 1686 | version = "0.2.4" 1687 | source = "registry+https://github.com/rust-lang/crates.io-index" 1688 | checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" 1689 | dependencies = [ 1690 | "proc-macro2", 1691 | "quote", 1692 | "syn 2.0.89", 1693 | ] 1694 | 1695 | [[package]] 1696 | name = "is_terminal_polyfill" 1697 | version = "1.70.1" 1698 | source = "registry+https://github.com/rust-lang/crates.io-index" 1699 | checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" 1700 | 1701 | [[package]] 1702 | name = "itertools" 1703 | version = "0.12.1" 1704 | source = "registry+https://github.com/rust-lang/crates.io-index" 1705 | checksum = "ba291022dbbd398a455acf126c1e341954079855bc60dfdda641363bd6922569" 1706 | dependencies = [ 1707 | "either", 1708 | ] 1709 | 1710 | [[package]] 1711 | name = "itoa" 1712 | version = "1.0.13" 1713 | source = "registry+https://github.com/rust-lang/crates.io-index" 1714 | checksum = "540654e97a3f4470a492cd30ff187bc95d89557a903a2bbf112e2fae98104ef2" 1715 | 1716 | [[package]] 1717 | name = "jobserver" 1718 | version = "0.1.32" 1719 | source = "registry+https://github.com/rust-lang/crates.io-index" 1720 | checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" 1721 | dependencies = [ 1722 | "libc", 1723 | ] 1724 | 1725 | [[package]] 1726 | name = "jpeg-decoder" 1727 | version = "0.3.1" 1728 | source = "registry+https://github.com/rust-lang/crates.io-index" 1729 | checksum = "f5d4a7da358eff58addd2877a45865158f0d78c911d43a5784ceb7bbf52833b0" 1730 | 1731 | [[package]] 1732 | name = "js-sys" 1733 | version = "0.3.72" 1734 | source = "registry+https://github.com/rust-lang/crates.io-index" 1735 | checksum = "6a88f1bda2bd75b0452a14784937d796722fdebfe50df998aeb3f0b7603019a9" 1736 | dependencies = [ 1737 | "wasm-bindgen", 1738 | ] 1739 | 1740 | [[package]] 1741 | name = "jsonwebtoken" 1742 | version = "9.3.0" 1743 | source = "registry+https://github.com/rust-lang/crates.io-index" 1744 | checksum = "b9ae10193d25051e74945f1ea2d0b42e03cc3b890f7e4cc5faa44997d808193f" 1745 | dependencies = [ 1746 | "base64 0.21.7", 1747 | "js-sys", 1748 | "pem", 1749 | "ring", 1750 | "serde", 1751 | "serde_json", 1752 | "simple_asn1", 1753 | ] 1754 | 1755 | [[package]] 1756 | name = "language-tags" 1757 | version = "0.3.2" 1758 | source = "registry+https://github.com/rust-lang/crates.io-index" 1759 | checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" 1760 | 1761 | [[package]] 1762 | name = "lazy_static" 1763 | version = "1.5.0" 1764 | source = "registry+https://github.com/rust-lang/crates.io-index" 1765 | checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 1766 | dependencies = [ 1767 | "spin", 1768 | ] 1769 | 1770 | [[package]] 1771 | name = "lebe" 1772 | version = "0.5.2" 1773 | source = "registry+https://github.com/rust-lang/crates.io-index" 1774 | checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" 1775 | 1776 | [[package]] 1777 | name = "libc" 1778 | version = "0.2.164" 1779 | source = "registry+https://github.com/rust-lang/crates.io-index" 1780 | checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f" 1781 | 1782 | [[package]] 1783 | name = "libfuzzer-sys" 1784 | version = "0.4.8" 1785 | source = "registry+https://github.com/rust-lang/crates.io-index" 1786 | checksum = "9b9569d2f74e257076d8c6bfa73fb505b46b851e51ddaecc825944aa3bed17fa" 1787 | dependencies = [ 1788 | "arbitrary", 1789 | "cc", 1790 | ] 1791 | 1792 | [[package]] 1793 | name = "libm" 1794 | version = "0.2.11" 1795 | source = "registry+https://github.com/rust-lang/crates.io-index" 1796 | checksum = "8355be11b20d696c8f18f6cc018c4e372165b1fa8126cef092399c9951984ffa" 1797 | 1798 | [[package]] 1799 | name = "libsqlite3-sys" 1800 | version = "0.30.1" 1801 | source = "registry+https://github.com/rust-lang/crates.io-index" 1802 | checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149" 1803 | dependencies = [ 1804 | "cc", 1805 | "pkg-config", 1806 | "vcpkg", 1807 | ] 1808 | 1809 | [[package]] 1810 | name = "linux-raw-sys" 1811 | version = "0.4.14" 1812 | source = "registry+https://github.com/rust-lang/crates.io-index" 1813 | checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" 1814 | 1815 | [[package]] 1816 | name = "litemap" 1817 | version = "0.7.4" 1818 | source = "registry+https://github.com/rust-lang/crates.io-index" 1819 | checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" 1820 | 1821 | [[package]] 1822 | name = "litrs" 1823 | version = "0.4.1" 1824 | source = "registry+https://github.com/rust-lang/crates.io-index" 1825 | checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5" 1826 | 1827 | [[package]] 1828 | name = "local-channel" 1829 | version = "0.1.5" 1830 | source = "registry+https://github.com/rust-lang/crates.io-index" 1831 | checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8" 1832 | dependencies = [ 1833 | "futures-core", 1834 | "futures-sink", 1835 | "local-waker", 1836 | ] 1837 | 1838 | [[package]] 1839 | name = "local-waker" 1840 | version = "0.1.4" 1841 | source = "registry+https://github.com/rust-lang/crates.io-index" 1842 | checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487" 1843 | 1844 | [[package]] 1845 | name = "lock_api" 1846 | version = "0.4.12" 1847 | source = "registry+https://github.com/rust-lang/crates.io-index" 1848 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 1849 | dependencies = [ 1850 | "autocfg", 1851 | "scopeguard", 1852 | ] 1853 | 1854 | [[package]] 1855 | name = "lockfree-object-pool" 1856 | version = "0.1.6" 1857 | source = "registry+https://github.com/rust-lang/crates.io-index" 1858 | checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e" 1859 | 1860 | [[package]] 1861 | name = "log" 1862 | version = "0.4.22" 1863 | source = "registry+https://github.com/rust-lang/crates.io-index" 1864 | checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 1865 | 1866 | [[package]] 1867 | name = "loop9" 1868 | version = "0.1.5" 1869 | source = "registry+https://github.com/rust-lang/crates.io-index" 1870 | checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" 1871 | dependencies = [ 1872 | "imgref", 1873 | ] 1874 | 1875 | [[package]] 1876 | name = "maybe-rayon" 1877 | version = "0.1.1" 1878 | source = "registry+https://github.com/rust-lang/crates.io-index" 1879 | checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" 1880 | dependencies = [ 1881 | "cfg-if", 1882 | "rayon", 1883 | ] 1884 | 1885 | [[package]] 1886 | name = "md-5" 1887 | version = "0.10.6" 1888 | source = "registry+https://github.com/rust-lang/crates.io-index" 1889 | checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf" 1890 | dependencies = [ 1891 | "cfg-if", 1892 | "digest", 1893 | ] 1894 | 1895 | [[package]] 1896 | name = "memchr" 1897 | version = "2.7.4" 1898 | source = "registry+https://github.com/rust-lang/crates.io-index" 1899 | checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" 1900 | 1901 | [[package]] 1902 | name = "mime" 1903 | version = "0.3.17" 1904 | source = "registry+https://github.com/rust-lang/crates.io-index" 1905 | checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 1906 | 1907 | [[package]] 1908 | name = "mime_guess" 1909 | version = "2.0.5" 1910 | source = "registry+https://github.com/rust-lang/crates.io-index" 1911 | checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" 1912 | dependencies = [ 1913 | "mime", 1914 | "unicase", 1915 | ] 1916 | 1917 | [[package]] 1918 | name = "minimal-lexical" 1919 | version = "0.2.1" 1920 | source = "registry+https://github.com/rust-lang/crates.io-index" 1921 | checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" 1922 | 1923 | [[package]] 1924 | name = "miniz_oxide" 1925 | version = "0.8.0" 1926 | source = "registry+https://github.com/rust-lang/crates.io-index" 1927 | checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" 1928 | dependencies = [ 1929 | "adler2", 1930 | "simd-adler32", 1931 | ] 1932 | 1933 | [[package]] 1934 | name = "mio" 1935 | version = "1.0.2" 1936 | source = "registry+https://github.com/rust-lang/crates.io-index" 1937 | checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" 1938 | dependencies = [ 1939 | "hermit-abi", 1940 | "libc", 1941 | "log", 1942 | "wasi", 1943 | "windows-sys 0.52.0", 1944 | ] 1945 | 1946 | [[package]] 1947 | name = "new_debug_unreachable" 1948 | version = "1.0.6" 1949 | source = "registry+https://github.com/rust-lang/crates.io-index" 1950 | checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" 1951 | 1952 | [[package]] 1953 | name = "nom" 1954 | version = "7.1.3" 1955 | source = "registry+https://github.com/rust-lang/crates.io-index" 1956 | checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" 1957 | dependencies = [ 1958 | "memchr", 1959 | "minimal-lexical", 1960 | ] 1961 | 1962 | [[package]] 1963 | name = "noop_proc_macro" 1964 | version = "0.3.0" 1965 | source = "registry+https://github.com/rust-lang/crates.io-index" 1966 | checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" 1967 | 1968 | [[package]] 1969 | name = "num-bigint" 1970 | version = "0.4.6" 1971 | source = "registry+https://github.com/rust-lang/crates.io-index" 1972 | checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" 1973 | dependencies = [ 1974 | "num-integer", 1975 | "num-traits", 1976 | ] 1977 | 1978 | [[package]] 1979 | name = "num-bigint-dig" 1980 | version = "0.8.4" 1981 | source = "registry+https://github.com/rust-lang/crates.io-index" 1982 | checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" 1983 | dependencies = [ 1984 | "byteorder", 1985 | "lazy_static", 1986 | "libm", 1987 | "num-integer", 1988 | "num-iter", 1989 | "num-traits", 1990 | "rand", 1991 | "smallvec", 1992 | "zeroize", 1993 | ] 1994 | 1995 | [[package]] 1996 | name = "num-conv" 1997 | version = "0.1.0" 1998 | source = "registry+https://github.com/rust-lang/crates.io-index" 1999 | checksum = "51d515d32fb182ee37cda2ccdcb92950d6a3c2893aa280e540671c2cd0f3b1d9" 2000 | 2001 | [[package]] 2002 | name = "num-derive" 2003 | version = "0.4.2" 2004 | source = "registry+https://github.com/rust-lang/crates.io-index" 2005 | checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" 2006 | dependencies = [ 2007 | "proc-macro2", 2008 | "quote", 2009 | "syn 2.0.89", 2010 | ] 2011 | 2012 | [[package]] 2013 | name = "num-integer" 2014 | version = "0.1.46" 2015 | source = "registry+https://github.com/rust-lang/crates.io-index" 2016 | checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" 2017 | dependencies = [ 2018 | "num-traits", 2019 | ] 2020 | 2021 | [[package]] 2022 | name = "num-iter" 2023 | version = "0.1.45" 2024 | source = "registry+https://github.com/rust-lang/crates.io-index" 2025 | checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" 2026 | dependencies = [ 2027 | "autocfg", 2028 | "num-integer", 2029 | "num-traits", 2030 | ] 2031 | 2032 | [[package]] 2033 | name = "num-rational" 2034 | version = "0.4.2" 2035 | source = "registry+https://github.com/rust-lang/crates.io-index" 2036 | checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" 2037 | dependencies = [ 2038 | "num-bigint", 2039 | "num-integer", 2040 | "num-traits", 2041 | ] 2042 | 2043 | [[package]] 2044 | name = "num-traits" 2045 | version = "0.2.19" 2046 | source = "registry+https://github.com/rust-lang/crates.io-index" 2047 | checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 2048 | dependencies = [ 2049 | "autocfg", 2050 | "libm", 2051 | ] 2052 | 2053 | [[package]] 2054 | name = "object" 2055 | version = "0.36.5" 2056 | source = "registry+https://github.com/rust-lang/crates.io-index" 2057 | checksum = "aedf0a2d09c573ed1d8d85b30c119153926a2b36dce0ab28322c09a117a4683e" 2058 | dependencies = [ 2059 | "memchr", 2060 | ] 2061 | 2062 | [[package]] 2063 | name = "once_cell" 2064 | version = "1.20.2" 2065 | source = "registry+https://github.com/rust-lang/crates.io-index" 2066 | checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" 2067 | 2068 | [[package]] 2069 | name = "parking" 2070 | version = "2.2.1" 2071 | source = "registry+https://github.com/rust-lang/crates.io-index" 2072 | checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" 2073 | 2074 | [[package]] 2075 | name = "parking_lot" 2076 | version = "0.12.3" 2077 | source = "registry+https://github.com/rust-lang/crates.io-index" 2078 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 2079 | dependencies = [ 2080 | "lock_api", 2081 | "parking_lot_core", 2082 | ] 2083 | 2084 | [[package]] 2085 | name = "parking_lot_core" 2086 | version = "0.9.10" 2087 | source = "registry+https://github.com/rust-lang/crates.io-index" 2088 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 2089 | dependencies = [ 2090 | "cfg-if", 2091 | "libc", 2092 | "redox_syscall", 2093 | "smallvec", 2094 | "windows-targets 0.52.6", 2095 | ] 2096 | 2097 | [[package]] 2098 | name = "parse-size" 2099 | version = "1.1.0" 2100 | source = "registry+https://github.com/rust-lang/crates.io-index" 2101 | checksum = "487f2ccd1e17ce8c1bfab3a65c89525af41cfad4c8659021a1e9a2aacd73b89b" 2102 | 2103 | [[package]] 2104 | name = "paste" 2105 | version = "1.0.15" 2106 | source = "registry+https://github.com/rust-lang/crates.io-index" 2107 | checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" 2108 | 2109 | [[package]] 2110 | name = "pem" 2111 | version = "3.0.4" 2112 | source = "registry+https://github.com/rust-lang/crates.io-index" 2113 | checksum = "8e459365e590736a54c3fa561947c84837534b8e9af6fc5bf781307e82658fae" 2114 | dependencies = [ 2115 | "base64 0.22.1", 2116 | "serde", 2117 | ] 2118 | 2119 | [[package]] 2120 | name = "pem-rfc7468" 2121 | version = "0.7.0" 2122 | source = "registry+https://github.com/rust-lang/crates.io-index" 2123 | checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412" 2124 | dependencies = [ 2125 | "base64ct", 2126 | ] 2127 | 2128 | [[package]] 2129 | name = "percent-encoding" 2130 | version = "2.3.1" 2131 | source = "registry+https://github.com/rust-lang/crates.io-index" 2132 | checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" 2133 | 2134 | [[package]] 2135 | name = "pin-project-lite" 2136 | version = "0.2.15" 2137 | source = "registry+https://github.com/rust-lang/crates.io-index" 2138 | checksum = "915a1e146535de9163f3987b8944ed8cf49a18bb0056bcebcdcece385cece4ff" 2139 | 2140 | [[package]] 2141 | name = "pin-utils" 2142 | version = "0.1.0" 2143 | source = "registry+https://github.com/rust-lang/crates.io-index" 2144 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 2145 | 2146 | [[package]] 2147 | name = "pkcs1" 2148 | version = "0.7.5" 2149 | source = "registry+https://github.com/rust-lang/crates.io-index" 2150 | checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" 2151 | dependencies = [ 2152 | "der", 2153 | "pkcs8", 2154 | "spki", 2155 | ] 2156 | 2157 | [[package]] 2158 | name = "pkcs8" 2159 | version = "0.10.2" 2160 | source = "registry+https://github.com/rust-lang/crates.io-index" 2161 | checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" 2162 | dependencies = [ 2163 | "der", 2164 | "spki", 2165 | ] 2166 | 2167 | [[package]] 2168 | name = "pkg-config" 2169 | version = "0.3.31" 2170 | source = "registry+https://github.com/rust-lang/crates.io-index" 2171 | checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2" 2172 | 2173 | [[package]] 2174 | name = "png" 2175 | version = "0.17.14" 2176 | source = "registry+https://github.com/rust-lang/crates.io-index" 2177 | checksum = "52f9d46a34a05a6a57566bc2bfae066ef07585a6e3fa30fbbdff5936380623f0" 2178 | dependencies = [ 2179 | "bitflags 1.3.2", 2180 | "crc32fast", 2181 | "fdeflate", 2182 | "flate2", 2183 | "miniz_oxide", 2184 | ] 2185 | 2186 | [[package]] 2187 | name = "powerfmt" 2188 | version = "0.2.0" 2189 | source = "registry+https://github.com/rust-lang/crates.io-index" 2190 | checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" 2191 | 2192 | [[package]] 2193 | name = "ppv-lite86" 2194 | version = "0.2.20" 2195 | source = "registry+https://github.com/rust-lang/crates.io-index" 2196 | checksum = "77957b295656769bb8ad2b6a6b09d897d94f05c41b069aede1fcdaa675eaea04" 2197 | dependencies = [ 2198 | "zerocopy", 2199 | ] 2200 | 2201 | [[package]] 2202 | name = "proc-macro-crate" 2203 | version = "3.2.0" 2204 | source = "registry+https://github.com/rust-lang/crates.io-index" 2205 | checksum = "8ecf48c7ca261d60b74ab1a7b20da18bede46776b2e55535cb958eb595c5fa7b" 2206 | dependencies = [ 2207 | "toml_edit", 2208 | ] 2209 | 2210 | [[package]] 2211 | name = "proc-macro-error-attr2" 2212 | version = "2.0.0" 2213 | source = "registry+https://github.com/rust-lang/crates.io-index" 2214 | checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" 2215 | dependencies = [ 2216 | "proc-macro2", 2217 | "quote", 2218 | ] 2219 | 2220 | [[package]] 2221 | name = "proc-macro-error2" 2222 | version = "2.0.1" 2223 | source = "registry+https://github.com/rust-lang/crates.io-index" 2224 | checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" 2225 | dependencies = [ 2226 | "proc-macro-error-attr2", 2227 | "proc-macro2", 2228 | "quote", 2229 | "syn 2.0.89", 2230 | ] 2231 | 2232 | [[package]] 2233 | name = "proc-macro2" 2234 | version = "1.0.92" 2235 | source = "registry+https://github.com/rust-lang/crates.io-index" 2236 | checksum = "37d3544b3f2748c54e147655edb5025752e2303145b5aefb3c3ea2c78b973bb0" 2237 | dependencies = [ 2238 | "unicode-ident", 2239 | ] 2240 | 2241 | [[package]] 2242 | name = "profiling" 2243 | version = "1.0.16" 2244 | source = "registry+https://github.com/rust-lang/crates.io-index" 2245 | checksum = "afbdc74edc00b6f6a218ca6a5364d6226a259d4b8ea1af4a0ea063f27e179f4d" 2246 | dependencies = [ 2247 | "profiling-procmacros", 2248 | ] 2249 | 2250 | [[package]] 2251 | name = "profiling-procmacros" 2252 | version = "1.0.16" 2253 | source = "registry+https://github.com/rust-lang/crates.io-index" 2254 | checksum = "a65f2e60fbf1063868558d69c6beacf412dc755f9fc020f514b7955fc914fe30" 2255 | dependencies = [ 2256 | "quote", 2257 | "syn 2.0.89", 2258 | ] 2259 | 2260 | [[package]] 2261 | name = "ptr_meta" 2262 | version = "0.1.4" 2263 | source = "registry+https://github.com/rust-lang/crates.io-index" 2264 | checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" 2265 | dependencies = [ 2266 | "ptr_meta_derive", 2267 | ] 2268 | 2269 | [[package]] 2270 | name = "ptr_meta_derive" 2271 | version = "0.1.4" 2272 | source = "registry+https://github.com/rust-lang/crates.io-index" 2273 | checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" 2274 | dependencies = [ 2275 | "proc-macro2", 2276 | "quote", 2277 | "syn 1.0.109", 2278 | ] 2279 | 2280 | [[package]] 2281 | name = "qoi" 2282 | version = "0.4.1" 2283 | source = "registry+https://github.com/rust-lang/crates.io-index" 2284 | checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" 2285 | dependencies = [ 2286 | "bytemuck", 2287 | ] 2288 | 2289 | [[package]] 2290 | name = "quick-error" 2291 | version = "2.0.1" 2292 | source = "registry+https://github.com/rust-lang/crates.io-index" 2293 | checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" 2294 | 2295 | [[package]] 2296 | name = "quote" 2297 | version = "1.0.37" 2298 | source = "registry+https://github.com/rust-lang/crates.io-index" 2299 | checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" 2300 | dependencies = [ 2301 | "proc-macro2", 2302 | ] 2303 | 2304 | [[package]] 2305 | name = "radium" 2306 | version = "0.7.0" 2307 | source = "registry+https://github.com/rust-lang/crates.io-index" 2308 | checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" 2309 | 2310 | [[package]] 2311 | name = "rand" 2312 | version = "0.8.5" 2313 | source = "registry+https://github.com/rust-lang/crates.io-index" 2314 | checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 2315 | dependencies = [ 2316 | "libc", 2317 | "rand_chacha", 2318 | "rand_core", 2319 | ] 2320 | 2321 | [[package]] 2322 | name = "rand_chacha" 2323 | version = "0.3.1" 2324 | source = "registry+https://github.com/rust-lang/crates.io-index" 2325 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 2326 | dependencies = [ 2327 | "ppv-lite86", 2328 | "rand_core", 2329 | ] 2330 | 2331 | [[package]] 2332 | name = "rand_core" 2333 | version = "0.6.4" 2334 | source = "registry+https://github.com/rust-lang/crates.io-index" 2335 | checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 2336 | dependencies = [ 2337 | "getrandom", 2338 | ] 2339 | 2340 | [[package]] 2341 | name = "rav1e" 2342 | version = "0.7.1" 2343 | source = "registry+https://github.com/rust-lang/crates.io-index" 2344 | checksum = "cd87ce80a7665b1cce111f8a16c1f3929f6547ce91ade6addf4ec86a8dda5ce9" 2345 | dependencies = [ 2346 | "arbitrary", 2347 | "arg_enum_proc_macro", 2348 | "arrayvec", 2349 | "av1-grain", 2350 | "bitstream-io", 2351 | "built", 2352 | "cfg-if", 2353 | "interpolate_name", 2354 | "itertools", 2355 | "libc", 2356 | "libfuzzer-sys", 2357 | "log", 2358 | "maybe-rayon", 2359 | "new_debug_unreachable", 2360 | "noop_proc_macro", 2361 | "num-derive", 2362 | "num-traits", 2363 | "once_cell", 2364 | "paste", 2365 | "profiling", 2366 | "rand", 2367 | "rand_chacha", 2368 | "simd_helpers", 2369 | "system-deps", 2370 | "thiserror 1.0.69", 2371 | "v_frame", 2372 | "wasm-bindgen", 2373 | ] 2374 | 2375 | [[package]] 2376 | name = "ravif" 2377 | version = "0.11.11" 2378 | source = "registry+https://github.com/rust-lang/crates.io-index" 2379 | checksum = "2413fd96bd0ea5cdeeb37eaf446a22e6ed7b981d792828721e74ded1980a45c6" 2380 | dependencies = [ 2381 | "avif-serialize", 2382 | "imgref", 2383 | "loop9", 2384 | "quick-error", 2385 | "rav1e", 2386 | "rayon", 2387 | "rgb", 2388 | ] 2389 | 2390 | [[package]] 2391 | name = "rayon" 2392 | version = "1.10.0" 2393 | source = "registry+https://github.com/rust-lang/crates.io-index" 2394 | checksum = "b418a60154510ca1a002a752ca9714984e21e4241e804d32555251faf8b78ffa" 2395 | dependencies = [ 2396 | "either", 2397 | "rayon-core", 2398 | ] 2399 | 2400 | [[package]] 2401 | name = "rayon-core" 2402 | version = "1.12.1" 2403 | source = "registry+https://github.com/rust-lang/crates.io-index" 2404 | checksum = "1465873a3dfdaa8ae7cb14b4383657caab0b3e8a0aa9ae8e04b044854c8dfce2" 2405 | dependencies = [ 2406 | "crossbeam-deque", 2407 | "crossbeam-utils", 2408 | ] 2409 | 2410 | [[package]] 2411 | name = "redox_syscall" 2412 | version = "0.5.7" 2413 | source = "registry+https://github.com/rust-lang/crates.io-index" 2414 | checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" 2415 | dependencies = [ 2416 | "bitflags 2.6.0", 2417 | ] 2418 | 2419 | [[package]] 2420 | name = "regex" 2421 | version = "1.11.1" 2422 | source = "registry+https://github.com/rust-lang/crates.io-index" 2423 | checksum = "b544ef1b4eac5dc2db33ea63606ae9ffcfac26c1416a2806ae0bf5f56b201191" 2424 | dependencies = [ 2425 | "aho-corasick", 2426 | "memchr", 2427 | "regex-automata", 2428 | "regex-syntax", 2429 | ] 2430 | 2431 | [[package]] 2432 | name = "regex-automata" 2433 | version = "0.4.9" 2434 | source = "registry+https://github.com/rust-lang/crates.io-index" 2435 | checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908" 2436 | dependencies = [ 2437 | "aho-corasick", 2438 | "memchr", 2439 | "regex-syntax", 2440 | ] 2441 | 2442 | [[package]] 2443 | name = "regex-lite" 2444 | version = "0.1.6" 2445 | source = "registry+https://github.com/rust-lang/crates.io-index" 2446 | checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" 2447 | 2448 | [[package]] 2449 | name = "regex-syntax" 2450 | version = "0.8.5" 2451 | source = "registry+https://github.com/rust-lang/crates.io-index" 2452 | checksum = "2b15c43186be67a4fd63bee50d0303afffcef381492ebe2c5d87f324e1b8815c" 2453 | 2454 | [[package]] 2455 | name = "rend" 2456 | version = "0.4.2" 2457 | source = "registry+https://github.com/rust-lang/crates.io-index" 2458 | checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" 2459 | dependencies = [ 2460 | "bytecheck", 2461 | ] 2462 | 2463 | [[package]] 2464 | name = "rgb" 2465 | version = "0.8.50" 2466 | source = "registry+https://github.com/rust-lang/crates.io-index" 2467 | checksum = "57397d16646700483b67d2dd6511d79318f9d057fdbd21a4066aeac8b41d310a" 2468 | 2469 | [[package]] 2470 | name = "ring" 2471 | version = "0.17.8" 2472 | source = "registry+https://github.com/rust-lang/crates.io-index" 2473 | checksum = "c17fa4cb658e3583423e915b9f3acc01cceaee1860e33d59ebae66adc3a2dc0d" 2474 | dependencies = [ 2475 | "cc", 2476 | "cfg-if", 2477 | "getrandom", 2478 | "libc", 2479 | "spin", 2480 | "untrusted", 2481 | "windows-sys 0.52.0", 2482 | ] 2483 | 2484 | [[package]] 2485 | name = "rkyv" 2486 | version = "0.7.45" 2487 | source = "registry+https://github.com/rust-lang/crates.io-index" 2488 | checksum = "9008cd6385b9e161d8229e1f6549dd23c3d022f132a2ea37ac3a10ac4935779b" 2489 | dependencies = [ 2490 | "bitvec", 2491 | "bytecheck", 2492 | "bytes", 2493 | "hashbrown 0.12.3", 2494 | "ptr_meta", 2495 | "rend", 2496 | "rkyv_derive", 2497 | "seahash", 2498 | "tinyvec", 2499 | "uuid", 2500 | ] 2501 | 2502 | [[package]] 2503 | name = "rkyv_derive" 2504 | version = "0.7.45" 2505 | source = "registry+https://github.com/rust-lang/crates.io-index" 2506 | checksum = "503d1d27590a2b0a3a4ca4c94755aa2875657196ecbf401a42eff41d7de532c0" 2507 | dependencies = [ 2508 | "proc-macro2", 2509 | "quote", 2510 | "syn 1.0.109", 2511 | ] 2512 | 2513 | [[package]] 2514 | name = "rsa" 2515 | version = "0.9.6" 2516 | source = "registry+https://github.com/rust-lang/crates.io-index" 2517 | checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" 2518 | dependencies = [ 2519 | "const-oid", 2520 | "digest", 2521 | "num-bigint-dig", 2522 | "num-integer", 2523 | "num-traits", 2524 | "pkcs1", 2525 | "pkcs8", 2526 | "rand_core", 2527 | "signature", 2528 | "spki", 2529 | "subtle", 2530 | "zeroize", 2531 | ] 2532 | 2533 | [[package]] 2534 | name = "rust-embed" 2535 | version = "8.5.0" 2536 | source = "registry+https://github.com/rust-lang/crates.io-index" 2537 | checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" 2538 | dependencies = [ 2539 | "rust-embed-impl", 2540 | "rust-embed-utils", 2541 | "walkdir", 2542 | ] 2543 | 2544 | [[package]] 2545 | name = "rust-embed-impl" 2546 | version = "8.5.0" 2547 | source = "registry+https://github.com/rust-lang/crates.io-index" 2548 | checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" 2549 | dependencies = [ 2550 | "proc-macro2", 2551 | "quote", 2552 | "rust-embed-utils", 2553 | "syn 2.0.89", 2554 | "walkdir", 2555 | ] 2556 | 2557 | [[package]] 2558 | name = "rust-embed-utils" 2559 | version = "8.5.0" 2560 | source = "registry+https://github.com/rust-lang/crates.io-index" 2561 | checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" 2562 | dependencies = [ 2563 | "sha2", 2564 | "walkdir", 2565 | ] 2566 | 2567 | [[package]] 2568 | name = "rust_decimal" 2569 | version = "1.36.0" 2570 | source = "registry+https://github.com/rust-lang/crates.io-index" 2571 | checksum = "b082d80e3e3cc52b2ed634388d436fe1f4de6af5786cc2de9ba9737527bdf555" 2572 | dependencies = [ 2573 | "arrayvec", 2574 | "borsh", 2575 | "bytes", 2576 | "num-traits", 2577 | "rand", 2578 | "rkyv", 2579 | "serde", 2580 | "serde_json", 2581 | ] 2582 | 2583 | [[package]] 2584 | name = "rust_xlsxwriter" 2585 | version = "0.79.4" 2586 | source = "registry+https://github.com/rust-lang/crates.io-index" 2587 | checksum = "c743cb9f2a4524676020e26ee5f298445a82d882b09956811b1e78ca7e42b440" 2588 | dependencies = [ 2589 | "zip", 2590 | ] 2591 | 2592 | [[package]] 2593 | name = "rustc-demangle" 2594 | version = "0.1.24" 2595 | source = "registry+https://github.com/rust-lang/crates.io-index" 2596 | checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" 2597 | 2598 | [[package]] 2599 | name = "rustc_version" 2600 | version = "0.4.1" 2601 | source = "registry+https://github.com/rust-lang/crates.io-index" 2602 | checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" 2603 | dependencies = [ 2604 | "semver", 2605 | ] 2606 | 2607 | [[package]] 2608 | name = "rustix" 2609 | version = "0.38.41" 2610 | source = "registry+https://github.com/rust-lang/crates.io-index" 2611 | checksum = "d7f649912bc1495e167a6edee79151c84b1bad49748cb4f1f1167f459f6224f6" 2612 | dependencies = [ 2613 | "bitflags 2.6.0", 2614 | "errno", 2615 | "libc", 2616 | "linux-raw-sys", 2617 | "windows-sys 0.52.0", 2618 | ] 2619 | 2620 | [[package]] 2621 | name = "ryu" 2622 | version = "1.0.18" 2623 | source = "registry+https://github.com/rust-lang/crates.io-index" 2624 | checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" 2625 | 2626 | [[package]] 2627 | name = "same-file" 2628 | version = "1.0.6" 2629 | source = "registry+https://github.com/rust-lang/crates.io-index" 2630 | checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" 2631 | dependencies = [ 2632 | "winapi-util", 2633 | ] 2634 | 2635 | [[package]] 2636 | name = "sample_actix_webapi" 2637 | version = "2.0.0" 2638 | dependencies = [ 2639 | "actix", 2640 | "actix-cors", 2641 | "actix-files", 2642 | "actix-multipart", 2643 | "actix-web", 2644 | "actix-web-actors", 2645 | "base64ct", 2646 | "chrono", 2647 | "clap", 2648 | "dotenv", 2649 | "fast_image_resize", 2650 | "hex", 2651 | "image", 2652 | "jsonwebtoken", 2653 | "lazy_static", 2654 | "rust_xlsxwriter", 2655 | "sanitize-filename", 2656 | "serde", 2657 | "serde_json", 2658 | "sha2", 2659 | "sqlx", 2660 | "thiserror 2.0.3", 2661 | "utoipa", 2662 | "utoipa-swagger-ui", 2663 | "uuid", 2664 | "validator", 2665 | ] 2666 | 2667 | [[package]] 2668 | name = "sanitize-filename" 2669 | version = "0.6.0" 2670 | source = "registry+https://github.com/rust-lang/crates.io-index" 2671 | checksum = "bc984f4f9ceb736a7bb755c3e3bd17dc56370af2600c9780dcc48c66453da34d" 2672 | dependencies = [ 2673 | "regex", 2674 | ] 2675 | 2676 | [[package]] 2677 | name = "scopeguard" 2678 | version = "1.2.0" 2679 | source = "registry+https://github.com/rust-lang/crates.io-index" 2680 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 2681 | 2682 | [[package]] 2683 | name = "seahash" 2684 | version = "4.1.0" 2685 | source = "registry+https://github.com/rust-lang/crates.io-index" 2686 | checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" 2687 | 2688 | [[package]] 2689 | name = "semver" 2690 | version = "1.0.23" 2691 | source = "registry+https://github.com/rust-lang/crates.io-index" 2692 | checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" 2693 | 2694 | [[package]] 2695 | name = "serde" 2696 | version = "1.0.215" 2697 | source = "registry+https://github.com/rust-lang/crates.io-index" 2698 | checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f" 2699 | dependencies = [ 2700 | "serde_derive", 2701 | ] 2702 | 2703 | [[package]] 2704 | name = "serde_derive" 2705 | version = "1.0.215" 2706 | source = "registry+https://github.com/rust-lang/crates.io-index" 2707 | checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0" 2708 | dependencies = [ 2709 | "proc-macro2", 2710 | "quote", 2711 | "syn 2.0.89", 2712 | ] 2713 | 2714 | [[package]] 2715 | name = "serde_json" 2716 | version = "1.0.133" 2717 | source = "registry+https://github.com/rust-lang/crates.io-index" 2718 | checksum = "c7fceb2473b9166b2294ef05efcb65a3db80803f0b03ef86a5fc88a2b85ee377" 2719 | dependencies = [ 2720 | "itoa", 2721 | "memchr", 2722 | "ryu", 2723 | "serde", 2724 | ] 2725 | 2726 | [[package]] 2727 | name = "serde_plain" 2728 | version = "1.0.2" 2729 | source = "registry+https://github.com/rust-lang/crates.io-index" 2730 | checksum = "9ce1fc6db65a611022b23a0dec6975d63fb80a302cb3388835ff02c097258d50" 2731 | dependencies = [ 2732 | "serde", 2733 | ] 2734 | 2735 | [[package]] 2736 | name = "serde_spanned" 2737 | version = "0.6.8" 2738 | source = "registry+https://github.com/rust-lang/crates.io-index" 2739 | checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" 2740 | dependencies = [ 2741 | "serde", 2742 | ] 2743 | 2744 | [[package]] 2745 | name = "serde_urlencoded" 2746 | version = "0.7.1" 2747 | source = "registry+https://github.com/rust-lang/crates.io-index" 2748 | checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" 2749 | dependencies = [ 2750 | "form_urlencoded", 2751 | "itoa", 2752 | "ryu", 2753 | "serde", 2754 | ] 2755 | 2756 | [[package]] 2757 | name = "sha1" 2758 | version = "0.10.6" 2759 | source = "registry+https://github.com/rust-lang/crates.io-index" 2760 | checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" 2761 | dependencies = [ 2762 | "cfg-if", 2763 | "cpufeatures", 2764 | "digest", 2765 | ] 2766 | 2767 | [[package]] 2768 | name = "sha2" 2769 | version = "0.10.8" 2770 | source = "registry+https://github.com/rust-lang/crates.io-index" 2771 | checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" 2772 | dependencies = [ 2773 | "cfg-if", 2774 | "cpufeatures", 2775 | "digest", 2776 | ] 2777 | 2778 | [[package]] 2779 | name = "shlex" 2780 | version = "1.3.0" 2781 | source = "registry+https://github.com/rust-lang/crates.io-index" 2782 | checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 2783 | 2784 | [[package]] 2785 | name = "signal-hook-registry" 2786 | version = "1.4.2" 2787 | source = "registry+https://github.com/rust-lang/crates.io-index" 2788 | checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" 2789 | dependencies = [ 2790 | "libc", 2791 | ] 2792 | 2793 | [[package]] 2794 | name = "signature" 2795 | version = "2.2.0" 2796 | source = "registry+https://github.com/rust-lang/crates.io-index" 2797 | checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" 2798 | dependencies = [ 2799 | "digest", 2800 | "rand_core", 2801 | ] 2802 | 2803 | [[package]] 2804 | name = "simd-adler32" 2805 | version = "0.3.7" 2806 | source = "registry+https://github.com/rust-lang/crates.io-index" 2807 | checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" 2808 | 2809 | [[package]] 2810 | name = "simd_helpers" 2811 | version = "0.1.0" 2812 | source = "registry+https://github.com/rust-lang/crates.io-index" 2813 | checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" 2814 | dependencies = [ 2815 | "quote", 2816 | ] 2817 | 2818 | [[package]] 2819 | name = "simdutf8" 2820 | version = "0.1.5" 2821 | source = "registry+https://github.com/rust-lang/crates.io-index" 2822 | checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" 2823 | 2824 | [[package]] 2825 | name = "simple_asn1" 2826 | version = "0.6.2" 2827 | source = "registry+https://github.com/rust-lang/crates.io-index" 2828 | checksum = "adc4e5204eb1910f40f9cfa375f6f05b68c3abac4b6fd879c8ff5e7ae8a0a085" 2829 | dependencies = [ 2830 | "num-bigint", 2831 | "num-traits", 2832 | "thiserror 1.0.69", 2833 | "time", 2834 | ] 2835 | 2836 | [[package]] 2837 | name = "slab" 2838 | version = "0.4.9" 2839 | source = "registry+https://github.com/rust-lang/crates.io-index" 2840 | checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" 2841 | dependencies = [ 2842 | "autocfg", 2843 | ] 2844 | 2845 | [[package]] 2846 | name = "smallvec" 2847 | version = "1.13.2" 2848 | source = "registry+https://github.com/rust-lang/crates.io-index" 2849 | checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" 2850 | dependencies = [ 2851 | "serde", 2852 | ] 2853 | 2854 | [[package]] 2855 | name = "socket2" 2856 | version = "0.5.7" 2857 | source = "registry+https://github.com/rust-lang/crates.io-index" 2858 | checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c" 2859 | dependencies = [ 2860 | "libc", 2861 | "windows-sys 0.52.0", 2862 | ] 2863 | 2864 | [[package]] 2865 | name = "spin" 2866 | version = "0.9.8" 2867 | source = "registry+https://github.com/rust-lang/crates.io-index" 2868 | checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67" 2869 | dependencies = [ 2870 | "lock_api", 2871 | ] 2872 | 2873 | [[package]] 2874 | name = "spki" 2875 | version = "0.7.3" 2876 | source = "registry+https://github.com/rust-lang/crates.io-index" 2877 | checksum = "d91ed6c858b01f942cd56b37a94b3e0a1798290327d1236e4d9cf4eaca44d29d" 2878 | dependencies = [ 2879 | "base64ct", 2880 | "der", 2881 | ] 2882 | 2883 | [[package]] 2884 | name = "sqlformat" 2885 | version = "0.2.6" 2886 | source = "registry+https://github.com/rust-lang/crates.io-index" 2887 | checksum = "7bba3a93db0cc4f7bdece8bb09e77e2e785c20bfebf79eb8340ed80708048790" 2888 | dependencies = [ 2889 | "nom", 2890 | "unicode_categories", 2891 | ] 2892 | 2893 | [[package]] 2894 | name = "sqlx" 2895 | version = "0.8.2" 2896 | source = "registry+https://github.com/rust-lang/crates.io-index" 2897 | checksum = "93334716a037193fac19df402f8571269c84a00852f6a7066b5d2616dcd64d3e" 2898 | dependencies = [ 2899 | "sqlx-core", 2900 | "sqlx-macros", 2901 | "sqlx-mysql", 2902 | "sqlx-postgres", 2903 | "sqlx-sqlite", 2904 | ] 2905 | 2906 | [[package]] 2907 | name = "sqlx-core" 2908 | version = "0.8.2" 2909 | source = "registry+https://github.com/rust-lang/crates.io-index" 2910 | checksum = "d4d8060b456358185f7d50c55d9b5066ad956956fddec42ee2e8567134a8936e" 2911 | dependencies = [ 2912 | "atoi", 2913 | "byteorder", 2914 | "bytes", 2915 | "chrono", 2916 | "crc", 2917 | "crossbeam-queue", 2918 | "either", 2919 | "event-listener", 2920 | "futures-channel", 2921 | "futures-core", 2922 | "futures-intrusive", 2923 | "futures-io", 2924 | "futures-util", 2925 | "hashbrown 0.14.5", 2926 | "hashlink", 2927 | "hex", 2928 | "indexmap", 2929 | "log", 2930 | "memchr", 2931 | "once_cell", 2932 | "paste", 2933 | "percent-encoding", 2934 | "rust_decimal", 2935 | "serde", 2936 | "serde_json", 2937 | "sha2", 2938 | "smallvec", 2939 | "sqlformat", 2940 | "thiserror 1.0.69", 2941 | "tokio", 2942 | "tokio-stream", 2943 | "tracing", 2944 | "url", 2945 | "uuid", 2946 | ] 2947 | 2948 | [[package]] 2949 | name = "sqlx-macros" 2950 | version = "0.8.2" 2951 | source = "registry+https://github.com/rust-lang/crates.io-index" 2952 | checksum = "cac0692bcc9de3b073e8d747391827297e075c7710ff6276d9f7a1f3d58c6657" 2953 | dependencies = [ 2954 | "proc-macro2", 2955 | "quote", 2956 | "sqlx-core", 2957 | "sqlx-macros-core", 2958 | "syn 2.0.89", 2959 | ] 2960 | 2961 | [[package]] 2962 | name = "sqlx-macros-core" 2963 | version = "0.8.2" 2964 | source = "registry+https://github.com/rust-lang/crates.io-index" 2965 | checksum = "1804e8a7c7865599c9c79be146dc8a9fd8cc86935fa641d3ea58e5f0688abaa5" 2966 | dependencies = [ 2967 | "dotenvy", 2968 | "either", 2969 | "heck", 2970 | "hex", 2971 | "once_cell", 2972 | "proc-macro2", 2973 | "quote", 2974 | "serde", 2975 | "serde_json", 2976 | "sha2", 2977 | "sqlx-core", 2978 | "sqlx-mysql", 2979 | "sqlx-postgres", 2980 | "sqlx-sqlite", 2981 | "syn 2.0.89", 2982 | "tempfile", 2983 | "tokio", 2984 | "url", 2985 | ] 2986 | 2987 | [[package]] 2988 | name = "sqlx-mysql" 2989 | version = "0.8.2" 2990 | source = "registry+https://github.com/rust-lang/crates.io-index" 2991 | checksum = "64bb4714269afa44aef2755150a0fc19d756fb580a67db8885608cf02f47d06a" 2992 | dependencies = [ 2993 | "atoi", 2994 | "base64 0.22.1", 2995 | "bitflags 2.6.0", 2996 | "byteorder", 2997 | "bytes", 2998 | "chrono", 2999 | "crc", 3000 | "digest", 3001 | "dotenvy", 3002 | "either", 3003 | "futures-channel", 3004 | "futures-core", 3005 | "futures-io", 3006 | "futures-util", 3007 | "generic-array", 3008 | "hex", 3009 | "hkdf", 3010 | "hmac", 3011 | "itoa", 3012 | "log", 3013 | "md-5", 3014 | "memchr", 3015 | "once_cell", 3016 | "percent-encoding", 3017 | "rand", 3018 | "rsa", 3019 | "rust_decimal", 3020 | "serde", 3021 | "sha1", 3022 | "sha2", 3023 | "smallvec", 3024 | "sqlx-core", 3025 | "stringprep", 3026 | "thiserror 1.0.69", 3027 | "tracing", 3028 | "uuid", 3029 | "whoami", 3030 | ] 3031 | 3032 | [[package]] 3033 | name = "sqlx-postgres" 3034 | version = "0.8.2" 3035 | source = "registry+https://github.com/rust-lang/crates.io-index" 3036 | checksum = "6fa91a732d854c5d7726349bb4bb879bb9478993ceb764247660aee25f67c2f8" 3037 | dependencies = [ 3038 | "atoi", 3039 | "base64 0.22.1", 3040 | "bitflags 2.6.0", 3041 | "byteorder", 3042 | "chrono", 3043 | "crc", 3044 | "dotenvy", 3045 | "etcetera", 3046 | "futures-channel", 3047 | "futures-core", 3048 | "futures-io", 3049 | "futures-util", 3050 | "hex", 3051 | "hkdf", 3052 | "hmac", 3053 | "home", 3054 | "itoa", 3055 | "log", 3056 | "md-5", 3057 | "memchr", 3058 | "once_cell", 3059 | "rand", 3060 | "rust_decimal", 3061 | "serde", 3062 | "serde_json", 3063 | "sha2", 3064 | "smallvec", 3065 | "sqlx-core", 3066 | "stringprep", 3067 | "thiserror 1.0.69", 3068 | "tracing", 3069 | "uuid", 3070 | "whoami", 3071 | ] 3072 | 3073 | [[package]] 3074 | name = "sqlx-sqlite" 3075 | version = "0.8.2" 3076 | source = "registry+https://github.com/rust-lang/crates.io-index" 3077 | checksum = "d5b2cf34a45953bfd3daaf3db0f7a7878ab9b7a6b91b422d24a7a9e4c857b680" 3078 | dependencies = [ 3079 | "atoi", 3080 | "chrono", 3081 | "flume", 3082 | "futures-channel", 3083 | "futures-core", 3084 | "futures-executor", 3085 | "futures-intrusive", 3086 | "futures-util", 3087 | "libsqlite3-sys", 3088 | "log", 3089 | "percent-encoding", 3090 | "serde", 3091 | "serde_urlencoded", 3092 | "sqlx-core", 3093 | "tracing", 3094 | "url", 3095 | "uuid", 3096 | ] 3097 | 3098 | [[package]] 3099 | name = "stable_deref_trait" 3100 | version = "1.2.0" 3101 | source = "registry+https://github.com/rust-lang/crates.io-index" 3102 | checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" 3103 | 3104 | [[package]] 3105 | name = "stringprep" 3106 | version = "0.1.5" 3107 | source = "registry+https://github.com/rust-lang/crates.io-index" 3108 | checksum = "7b4df3d392d81bd458a8a621b8bffbd2302a12ffe288a9d931670948749463b1" 3109 | dependencies = [ 3110 | "unicode-bidi", 3111 | "unicode-normalization", 3112 | "unicode-properties", 3113 | ] 3114 | 3115 | [[package]] 3116 | name = "strsim" 3117 | version = "0.11.1" 3118 | source = "registry+https://github.com/rust-lang/crates.io-index" 3119 | checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" 3120 | 3121 | [[package]] 3122 | name = "subtle" 3123 | version = "2.6.1" 3124 | source = "registry+https://github.com/rust-lang/crates.io-index" 3125 | checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" 3126 | 3127 | [[package]] 3128 | name = "syn" 3129 | version = "1.0.109" 3130 | source = "registry+https://github.com/rust-lang/crates.io-index" 3131 | checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" 3132 | dependencies = [ 3133 | "proc-macro2", 3134 | "quote", 3135 | "unicode-ident", 3136 | ] 3137 | 3138 | [[package]] 3139 | name = "syn" 3140 | version = "2.0.89" 3141 | source = "registry+https://github.com/rust-lang/crates.io-index" 3142 | checksum = "44d46482f1c1c87acd84dea20c1bf5ebff4c757009ed6bf19cfd36fb10e92c4e" 3143 | dependencies = [ 3144 | "proc-macro2", 3145 | "quote", 3146 | "unicode-ident", 3147 | ] 3148 | 3149 | [[package]] 3150 | name = "synstructure" 3151 | version = "0.13.1" 3152 | source = "registry+https://github.com/rust-lang/crates.io-index" 3153 | checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" 3154 | dependencies = [ 3155 | "proc-macro2", 3156 | "quote", 3157 | "syn 2.0.89", 3158 | ] 3159 | 3160 | [[package]] 3161 | name = "system-deps" 3162 | version = "6.2.2" 3163 | source = "registry+https://github.com/rust-lang/crates.io-index" 3164 | checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" 3165 | dependencies = [ 3166 | "cfg-expr", 3167 | "heck", 3168 | "pkg-config", 3169 | "toml", 3170 | "version-compare", 3171 | ] 3172 | 3173 | [[package]] 3174 | name = "tap" 3175 | version = "1.0.1" 3176 | source = "registry+https://github.com/rust-lang/crates.io-index" 3177 | checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" 3178 | 3179 | [[package]] 3180 | name = "target-lexicon" 3181 | version = "0.12.16" 3182 | source = "registry+https://github.com/rust-lang/crates.io-index" 3183 | checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" 3184 | 3185 | [[package]] 3186 | name = "tempfile" 3187 | version = "3.14.0" 3188 | source = "registry+https://github.com/rust-lang/crates.io-index" 3189 | checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" 3190 | dependencies = [ 3191 | "cfg-if", 3192 | "fastrand", 3193 | "once_cell", 3194 | "rustix", 3195 | "windows-sys 0.59.0", 3196 | ] 3197 | 3198 | [[package]] 3199 | name = "thiserror" 3200 | version = "1.0.69" 3201 | source = "registry+https://github.com/rust-lang/crates.io-index" 3202 | checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 3203 | dependencies = [ 3204 | "thiserror-impl 1.0.69", 3205 | ] 3206 | 3207 | [[package]] 3208 | name = "thiserror" 3209 | version = "2.0.3" 3210 | source = "registry+https://github.com/rust-lang/crates.io-index" 3211 | checksum = "c006c85c7651b3cf2ada4584faa36773bd07bac24acfb39f3c431b36d7e667aa" 3212 | dependencies = [ 3213 | "thiserror-impl 2.0.3", 3214 | ] 3215 | 3216 | [[package]] 3217 | name = "thiserror-impl" 3218 | version = "1.0.69" 3219 | source = "registry+https://github.com/rust-lang/crates.io-index" 3220 | checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 3221 | dependencies = [ 3222 | "proc-macro2", 3223 | "quote", 3224 | "syn 2.0.89", 3225 | ] 3226 | 3227 | [[package]] 3228 | name = "thiserror-impl" 3229 | version = "2.0.3" 3230 | source = "registry+https://github.com/rust-lang/crates.io-index" 3231 | checksum = "f077553d607adc1caf65430528a576c757a71ed73944b66ebb58ef2bbd243568" 3232 | dependencies = [ 3233 | "proc-macro2", 3234 | "quote", 3235 | "syn 2.0.89", 3236 | ] 3237 | 3238 | [[package]] 3239 | name = "tiff" 3240 | version = "0.9.1" 3241 | source = "registry+https://github.com/rust-lang/crates.io-index" 3242 | checksum = "ba1310fcea54c6a9a4fd1aad794ecc02c31682f6bfbecdf460bf19533eed1e3e" 3243 | dependencies = [ 3244 | "flate2", 3245 | "jpeg-decoder", 3246 | "weezl", 3247 | ] 3248 | 3249 | [[package]] 3250 | name = "time" 3251 | version = "0.3.36" 3252 | source = "registry+https://github.com/rust-lang/crates.io-index" 3253 | checksum = "5dfd88e563464686c916c7e46e623e520ddc6d79fa6641390f2e3fa86e83e885" 3254 | dependencies = [ 3255 | "deranged", 3256 | "itoa", 3257 | "num-conv", 3258 | "powerfmt", 3259 | "serde", 3260 | "time-core", 3261 | "time-macros", 3262 | ] 3263 | 3264 | [[package]] 3265 | name = "time-core" 3266 | version = "0.1.2" 3267 | source = "registry+https://github.com/rust-lang/crates.io-index" 3268 | checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" 3269 | 3270 | [[package]] 3271 | name = "time-macros" 3272 | version = "0.2.18" 3273 | source = "registry+https://github.com/rust-lang/crates.io-index" 3274 | checksum = "3f252a68540fde3a3877aeea552b832b40ab9a69e318efd078774a01ddee1ccf" 3275 | dependencies = [ 3276 | "num-conv", 3277 | "time-core", 3278 | ] 3279 | 3280 | [[package]] 3281 | name = "tinystr" 3282 | version = "0.7.6" 3283 | source = "registry+https://github.com/rust-lang/crates.io-index" 3284 | checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" 3285 | dependencies = [ 3286 | "displaydoc", 3287 | "zerovec", 3288 | ] 3289 | 3290 | [[package]] 3291 | name = "tinyvec" 3292 | version = "1.8.0" 3293 | source = "registry+https://github.com/rust-lang/crates.io-index" 3294 | checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" 3295 | dependencies = [ 3296 | "tinyvec_macros", 3297 | ] 3298 | 3299 | [[package]] 3300 | name = "tinyvec_macros" 3301 | version = "0.1.1" 3302 | source = "registry+https://github.com/rust-lang/crates.io-index" 3303 | checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" 3304 | 3305 | [[package]] 3306 | name = "tokio" 3307 | version = "1.41.1" 3308 | source = "registry+https://github.com/rust-lang/crates.io-index" 3309 | checksum = "22cfb5bee7a6a52939ca9224d6ac897bb669134078daa8735560897f69de4d33" 3310 | dependencies = [ 3311 | "backtrace", 3312 | "bytes", 3313 | "libc", 3314 | "mio", 3315 | "parking_lot", 3316 | "pin-project-lite", 3317 | "signal-hook-registry", 3318 | "socket2", 3319 | "windows-sys 0.52.0", 3320 | ] 3321 | 3322 | [[package]] 3323 | name = "tokio-stream" 3324 | version = "0.1.16" 3325 | source = "registry+https://github.com/rust-lang/crates.io-index" 3326 | checksum = "4f4e6ce100d0eb49a2734f8c0812bcd324cf357d21810932c5df6b96ef2b86f1" 3327 | dependencies = [ 3328 | "futures-core", 3329 | "pin-project-lite", 3330 | "tokio", 3331 | ] 3332 | 3333 | [[package]] 3334 | name = "tokio-util" 3335 | version = "0.7.12" 3336 | source = "registry+https://github.com/rust-lang/crates.io-index" 3337 | checksum = "61e7c3654c13bcd040d4a03abee2c75b1d14a37b423cf5a813ceae1cc903ec6a" 3338 | dependencies = [ 3339 | "bytes", 3340 | "futures-core", 3341 | "futures-sink", 3342 | "pin-project-lite", 3343 | "tokio", 3344 | ] 3345 | 3346 | [[package]] 3347 | name = "toml" 3348 | version = "0.8.19" 3349 | source = "registry+https://github.com/rust-lang/crates.io-index" 3350 | checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" 3351 | dependencies = [ 3352 | "serde", 3353 | "serde_spanned", 3354 | "toml_datetime", 3355 | "toml_edit", 3356 | ] 3357 | 3358 | [[package]] 3359 | name = "toml_datetime" 3360 | version = "0.6.8" 3361 | source = "registry+https://github.com/rust-lang/crates.io-index" 3362 | checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" 3363 | dependencies = [ 3364 | "serde", 3365 | ] 3366 | 3367 | [[package]] 3368 | name = "toml_edit" 3369 | version = "0.22.22" 3370 | source = "registry+https://github.com/rust-lang/crates.io-index" 3371 | checksum = "4ae48d6208a266e853d946088ed816055e556cc6028c5e8e2b84d9fa5dd7c7f5" 3372 | dependencies = [ 3373 | "indexmap", 3374 | "serde", 3375 | "serde_spanned", 3376 | "toml_datetime", 3377 | "winnow", 3378 | ] 3379 | 3380 | [[package]] 3381 | name = "tracing" 3382 | version = "0.1.40" 3383 | source = "registry+https://github.com/rust-lang/crates.io-index" 3384 | checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" 3385 | dependencies = [ 3386 | "log", 3387 | "pin-project-lite", 3388 | "tracing-attributes", 3389 | "tracing-core", 3390 | ] 3391 | 3392 | [[package]] 3393 | name = "tracing-attributes" 3394 | version = "0.1.27" 3395 | source = "registry+https://github.com/rust-lang/crates.io-index" 3396 | checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" 3397 | dependencies = [ 3398 | "proc-macro2", 3399 | "quote", 3400 | "syn 2.0.89", 3401 | ] 3402 | 3403 | [[package]] 3404 | name = "tracing-core" 3405 | version = "0.1.32" 3406 | source = "registry+https://github.com/rust-lang/crates.io-index" 3407 | checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" 3408 | dependencies = [ 3409 | "once_cell", 3410 | ] 3411 | 3412 | [[package]] 3413 | name = "typenum" 3414 | version = "1.17.0" 3415 | source = "registry+https://github.com/rust-lang/crates.io-index" 3416 | checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" 3417 | 3418 | [[package]] 3419 | name = "unicase" 3420 | version = "2.8.0" 3421 | source = "registry+https://github.com/rust-lang/crates.io-index" 3422 | checksum = "7e51b68083f157f853b6379db119d1c1be0e6e4dec98101079dec41f6f5cf6df" 3423 | 3424 | [[package]] 3425 | name = "unicode-bidi" 3426 | version = "0.3.17" 3427 | source = "registry+https://github.com/rust-lang/crates.io-index" 3428 | checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" 3429 | 3430 | [[package]] 3431 | name = "unicode-ident" 3432 | version = "1.0.14" 3433 | source = "registry+https://github.com/rust-lang/crates.io-index" 3434 | checksum = "adb9e6ca4f869e1180728b7950e35922a7fc6397f7b641499e8f3ef06e50dc83" 3435 | 3436 | [[package]] 3437 | name = "unicode-normalization" 3438 | version = "0.1.24" 3439 | source = "registry+https://github.com/rust-lang/crates.io-index" 3440 | checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" 3441 | dependencies = [ 3442 | "tinyvec", 3443 | ] 3444 | 3445 | [[package]] 3446 | name = "unicode-properties" 3447 | version = "0.1.3" 3448 | source = "registry+https://github.com/rust-lang/crates.io-index" 3449 | checksum = "e70f2a8b45122e719eb623c01822704c4e0907e7e426a05927e1a1cfff5b75d0" 3450 | 3451 | [[package]] 3452 | name = "unicode_categories" 3453 | version = "0.1.1" 3454 | source = "registry+https://github.com/rust-lang/crates.io-index" 3455 | checksum = "39ec24b3121d976906ece63c9daad25b85969647682eee313cb5779fdd69e14e" 3456 | 3457 | [[package]] 3458 | name = "untrusted" 3459 | version = "0.9.0" 3460 | source = "registry+https://github.com/rust-lang/crates.io-index" 3461 | checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" 3462 | 3463 | [[package]] 3464 | name = "url" 3465 | version = "2.5.4" 3466 | source = "registry+https://github.com/rust-lang/crates.io-index" 3467 | checksum = "32f8b686cadd1473f4bd0117a5d28d36b1ade384ea9b5069a1c40aefed7fda60" 3468 | dependencies = [ 3469 | "form_urlencoded", 3470 | "idna", 3471 | "percent-encoding", 3472 | ] 3473 | 3474 | [[package]] 3475 | name = "utf16_iter" 3476 | version = "1.0.5" 3477 | source = "registry+https://github.com/rust-lang/crates.io-index" 3478 | checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" 3479 | 3480 | [[package]] 3481 | name = "utf8_iter" 3482 | version = "1.0.4" 3483 | source = "registry+https://github.com/rust-lang/crates.io-index" 3484 | checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" 3485 | 3486 | [[package]] 3487 | name = "utf8parse" 3488 | version = "0.2.2" 3489 | source = "registry+https://github.com/rust-lang/crates.io-index" 3490 | checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" 3491 | 3492 | [[package]] 3493 | name = "utoipa" 3494 | version = "5.2.0" 3495 | source = "registry+https://github.com/rust-lang/crates.io-index" 3496 | checksum = "514a48569e4e21c86d0b84b5612b5e73c0b2cf09db63260134ba426d4e8ea714" 3497 | dependencies = [ 3498 | "indexmap", 3499 | "serde", 3500 | "serde_json", 3501 | "utoipa-gen", 3502 | ] 3503 | 3504 | [[package]] 3505 | name = "utoipa-gen" 3506 | version = "5.2.0" 3507 | source = "registry+https://github.com/rust-lang/crates.io-index" 3508 | checksum = "5629efe65599d0ccd5d493688cbf6e03aa7c1da07fe59ff97cf5977ed0637f66" 3509 | dependencies = [ 3510 | "proc-macro2", 3511 | "quote", 3512 | "regex", 3513 | "syn 2.0.89", 3514 | "uuid", 3515 | ] 3516 | 3517 | [[package]] 3518 | name = "utoipa-swagger-ui" 3519 | version = "8.0.3" 3520 | source = "registry+https://github.com/rust-lang/crates.io-index" 3521 | checksum = "a5c80b4dd79ea382e8374d67dcce22b5c6663fa13a82ad3886441d1bbede5e35" 3522 | dependencies = [ 3523 | "actix-web", 3524 | "mime_guess", 3525 | "regex", 3526 | "rust-embed", 3527 | "serde", 3528 | "serde_json", 3529 | "url", 3530 | "utoipa", 3531 | "zip", 3532 | ] 3533 | 3534 | [[package]] 3535 | name = "uuid" 3536 | version = "1.11.0" 3537 | source = "registry+https://github.com/rust-lang/crates.io-index" 3538 | checksum = "f8c5f0a0af699448548ad1a2fbf920fb4bee257eae39953ba95cb84891a0446a" 3539 | dependencies = [ 3540 | "getrandom", 3541 | "serde", 3542 | ] 3543 | 3544 | [[package]] 3545 | name = "v_frame" 3546 | version = "0.3.8" 3547 | source = "registry+https://github.com/rust-lang/crates.io-index" 3548 | checksum = "d6f32aaa24bacd11e488aa9ba66369c7cd514885742c9fe08cfe85884db3e92b" 3549 | dependencies = [ 3550 | "aligned-vec", 3551 | "num-traits", 3552 | "wasm-bindgen", 3553 | ] 3554 | 3555 | [[package]] 3556 | name = "v_htmlescape" 3557 | version = "0.15.8" 3558 | source = "registry+https://github.com/rust-lang/crates.io-index" 3559 | checksum = "4e8257fbc510f0a46eb602c10215901938b5c2a7d5e70fc11483b1d3c9b5b18c" 3560 | 3561 | [[package]] 3562 | name = "validator" 3563 | version = "0.19.0" 3564 | source = "registry+https://github.com/rust-lang/crates.io-index" 3565 | checksum = "d0b4a29d8709210980a09379f27ee31549b73292c87ab9899beee1c0d3be6303" 3566 | dependencies = [ 3567 | "idna", 3568 | "once_cell", 3569 | "regex", 3570 | "serde", 3571 | "serde_derive", 3572 | "serde_json", 3573 | "url", 3574 | "validator_derive", 3575 | ] 3576 | 3577 | [[package]] 3578 | name = "validator_derive" 3579 | version = "0.19.0" 3580 | source = "registry+https://github.com/rust-lang/crates.io-index" 3581 | checksum = "bac855a2ce6f843beb229757e6e570a42e837bcb15e5f449dd48d5747d41bf77" 3582 | dependencies = [ 3583 | "darling", 3584 | "once_cell", 3585 | "proc-macro-error2", 3586 | "proc-macro2", 3587 | "quote", 3588 | "syn 2.0.89", 3589 | ] 3590 | 3591 | [[package]] 3592 | name = "vcpkg" 3593 | version = "0.2.15" 3594 | source = "registry+https://github.com/rust-lang/crates.io-index" 3595 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 3596 | 3597 | [[package]] 3598 | name = "version-compare" 3599 | version = "0.2.0" 3600 | source = "registry+https://github.com/rust-lang/crates.io-index" 3601 | checksum = "852e951cb7832cb45cb1169900d19760cfa39b82bc0ea9c0e5a14ae88411c98b" 3602 | 3603 | [[package]] 3604 | name = "version_check" 3605 | version = "0.9.5" 3606 | source = "registry+https://github.com/rust-lang/crates.io-index" 3607 | checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" 3608 | 3609 | [[package]] 3610 | name = "walkdir" 3611 | version = "2.5.0" 3612 | source = "registry+https://github.com/rust-lang/crates.io-index" 3613 | checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" 3614 | dependencies = [ 3615 | "same-file", 3616 | "winapi-util", 3617 | ] 3618 | 3619 | [[package]] 3620 | name = "wasi" 3621 | version = "0.11.0+wasi-snapshot-preview1" 3622 | source = "registry+https://github.com/rust-lang/crates.io-index" 3623 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 3624 | 3625 | [[package]] 3626 | name = "wasite" 3627 | version = "0.1.0" 3628 | source = "registry+https://github.com/rust-lang/crates.io-index" 3629 | checksum = "b8dad83b4f25e74f184f64c43b150b91efe7647395b42289f38e50566d82855b" 3630 | 3631 | [[package]] 3632 | name = "wasm-bindgen" 3633 | version = "0.2.95" 3634 | source = "registry+https://github.com/rust-lang/crates.io-index" 3635 | checksum = "128d1e363af62632b8eb57219c8fd7877144af57558fb2ef0368d0087bddeb2e" 3636 | dependencies = [ 3637 | "cfg-if", 3638 | "once_cell", 3639 | "wasm-bindgen-macro", 3640 | ] 3641 | 3642 | [[package]] 3643 | name = "wasm-bindgen-backend" 3644 | version = "0.2.95" 3645 | source = "registry+https://github.com/rust-lang/crates.io-index" 3646 | checksum = "cb6dd4d3ca0ddffd1dd1c9c04f94b868c37ff5fac97c30b97cff2d74fce3a358" 3647 | dependencies = [ 3648 | "bumpalo", 3649 | "log", 3650 | "once_cell", 3651 | "proc-macro2", 3652 | "quote", 3653 | "syn 2.0.89", 3654 | "wasm-bindgen-shared", 3655 | ] 3656 | 3657 | [[package]] 3658 | name = "wasm-bindgen-macro" 3659 | version = "0.2.95" 3660 | source = "registry+https://github.com/rust-lang/crates.io-index" 3661 | checksum = "e79384be7f8f5a9dd5d7167216f022090cf1f9ec128e6e6a482a2cb5c5422c56" 3662 | dependencies = [ 3663 | "quote", 3664 | "wasm-bindgen-macro-support", 3665 | ] 3666 | 3667 | [[package]] 3668 | name = "wasm-bindgen-macro-support" 3669 | version = "0.2.95" 3670 | source = "registry+https://github.com/rust-lang/crates.io-index" 3671 | checksum = "26c6ab57572f7a24a4985830b120de1594465e5d500f24afe89e16b4e833ef68" 3672 | dependencies = [ 3673 | "proc-macro2", 3674 | "quote", 3675 | "syn 2.0.89", 3676 | "wasm-bindgen-backend", 3677 | "wasm-bindgen-shared", 3678 | ] 3679 | 3680 | [[package]] 3681 | name = "wasm-bindgen-shared" 3682 | version = "0.2.95" 3683 | source = "registry+https://github.com/rust-lang/crates.io-index" 3684 | checksum = "65fc09f10666a9f147042251e0dda9c18f166ff7de300607007e96bdebc1068d" 3685 | 3686 | [[package]] 3687 | name = "weezl" 3688 | version = "0.1.8" 3689 | source = "registry+https://github.com/rust-lang/crates.io-index" 3690 | checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" 3691 | 3692 | [[package]] 3693 | name = "whoami" 3694 | version = "1.5.2" 3695 | source = "registry+https://github.com/rust-lang/crates.io-index" 3696 | checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" 3697 | dependencies = [ 3698 | "redox_syscall", 3699 | "wasite", 3700 | ] 3701 | 3702 | [[package]] 3703 | name = "winapi-util" 3704 | version = "0.1.9" 3705 | source = "registry+https://github.com/rust-lang/crates.io-index" 3706 | checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" 3707 | dependencies = [ 3708 | "windows-sys 0.59.0", 3709 | ] 3710 | 3711 | [[package]] 3712 | name = "windows-core" 3713 | version = "0.52.0" 3714 | source = "registry+https://github.com/rust-lang/crates.io-index" 3715 | checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" 3716 | dependencies = [ 3717 | "windows-targets 0.52.6", 3718 | ] 3719 | 3720 | [[package]] 3721 | name = "windows-sys" 3722 | version = "0.48.0" 3723 | source = "registry+https://github.com/rust-lang/crates.io-index" 3724 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 3725 | dependencies = [ 3726 | "windows-targets 0.48.5", 3727 | ] 3728 | 3729 | [[package]] 3730 | name = "windows-sys" 3731 | version = "0.52.0" 3732 | source = "registry+https://github.com/rust-lang/crates.io-index" 3733 | checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 3734 | dependencies = [ 3735 | "windows-targets 0.52.6", 3736 | ] 3737 | 3738 | [[package]] 3739 | name = "windows-sys" 3740 | version = "0.59.0" 3741 | source = "registry+https://github.com/rust-lang/crates.io-index" 3742 | checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" 3743 | dependencies = [ 3744 | "windows-targets 0.52.6", 3745 | ] 3746 | 3747 | [[package]] 3748 | name = "windows-targets" 3749 | version = "0.48.5" 3750 | source = "registry+https://github.com/rust-lang/crates.io-index" 3751 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 3752 | dependencies = [ 3753 | "windows_aarch64_gnullvm 0.48.5", 3754 | "windows_aarch64_msvc 0.48.5", 3755 | "windows_i686_gnu 0.48.5", 3756 | "windows_i686_msvc 0.48.5", 3757 | "windows_x86_64_gnu 0.48.5", 3758 | "windows_x86_64_gnullvm 0.48.5", 3759 | "windows_x86_64_msvc 0.48.5", 3760 | ] 3761 | 3762 | [[package]] 3763 | name = "windows-targets" 3764 | version = "0.52.6" 3765 | source = "registry+https://github.com/rust-lang/crates.io-index" 3766 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 3767 | dependencies = [ 3768 | "windows_aarch64_gnullvm 0.52.6", 3769 | "windows_aarch64_msvc 0.52.6", 3770 | "windows_i686_gnu 0.52.6", 3771 | "windows_i686_gnullvm", 3772 | "windows_i686_msvc 0.52.6", 3773 | "windows_x86_64_gnu 0.52.6", 3774 | "windows_x86_64_gnullvm 0.52.6", 3775 | "windows_x86_64_msvc 0.52.6", 3776 | ] 3777 | 3778 | [[package]] 3779 | name = "windows_aarch64_gnullvm" 3780 | version = "0.48.5" 3781 | source = "registry+https://github.com/rust-lang/crates.io-index" 3782 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 3783 | 3784 | [[package]] 3785 | name = "windows_aarch64_gnullvm" 3786 | version = "0.52.6" 3787 | source = "registry+https://github.com/rust-lang/crates.io-index" 3788 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 3789 | 3790 | [[package]] 3791 | name = "windows_aarch64_msvc" 3792 | version = "0.48.5" 3793 | source = "registry+https://github.com/rust-lang/crates.io-index" 3794 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 3795 | 3796 | [[package]] 3797 | name = "windows_aarch64_msvc" 3798 | version = "0.52.6" 3799 | source = "registry+https://github.com/rust-lang/crates.io-index" 3800 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 3801 | 3802 | [[package]] 3803 | name = "windows_i686_gnu" 3804 | version = "0.48.5" 3805 | source = "registry+https://github.com/rust-lang/crates.io-index" 3806 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 3807 | 3808 | [[package]] 3809 | name = "windows_i686_gnu" 3810 | version = "0.52.6" 3811 | source = "registry+https://github.com/rust-lang/crates.io-index" 3812 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 3813 | 3814 | [[package]] 3815 | name = "windows_i686_gnullvm" 3816 | version = "0.52.6" 3817 | source = "registry+https://github.com/rust-lang/crates.io-index" 3818 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 3819 | 3820 | [[package]] 3821 | name = "windows_i686_msvc" 3822 | version = "0.48.5" 3823 | source = "registry+https://github.com/rust-lang/crates.io-index" 3824 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 3825 | 3826 | [[package]] 3827 | name = "windows_i686_msvc" 3828 | version = "0.52.6" 3829 | source = "registry+https://github.com/rust-lang/crates.io-index" 3830 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 3831 | 3832 | [[package]] 3833 | name = "windows_x86_64_gnu" 3834 | version = "0.48.5" 3835 | source = "registry+https://github.com/rust-lang/crates.io-index" 3836 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 3837 | 3838 | [[package]] 3839 | name = "windows_x86_64_gnu" 3840 | version = "0.52.6" 3841 | source = "registry+https://github.com/rust-lang/crates.io-index" 3842 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 3843 | 3844 | [[package]] 3845 | name = "windows_x86_64_gnullvm" 3846 | version = "0.48.5" 3847 | source = "registry+https://github.com/rust-lang/crates.io-index" 3848 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 3849 | 3850 | [[package]] 3851 | name = "windows_x86_64_gnullvm" 3852 | version = "0.52.6" 3853 | source = "registry+https://github.com/rust-lang/crates.io-index" 3854 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 3855 | 3856 | [[package]] 3857 | name = "windows_x86_64_msvc" 3858 | version = "0.48.5" 3859 | source = "registry+https://github.com/rust-lang/crates.io-index" 3860 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 3861 | 3862 | [[package]] 3863 | name = "windows_x86_64_msvc" 3864 | version = "0.52.6" 3865 | source = "registry+https://github.com/rust-lang/crates.io-index" 3866 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 3867 | 3868 | [[package]] 3869 | name = "winnow" 3870 | version = "0.6.20" 3871 | source = "registry+https://github.com/rust-lang/crates.io-index" 3872 | checksum = "36c1fec1a2bb5866f07c25f68c26e565c4c200aebb96d7e55710c19d3e8ac49b" 3873 | dependencies = [ 3874 | "memchr", 3875 | ] 3876 | 3877 | [[package]] 3878 | name = "write16" 3879 | version = "1.0.0" 3880 | source = "registry+https://github.com/rust-lang/crates.io-index" 3881 | checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" 3882 | 3883 | [[package]] 3884 | name = "writeable" 3885 | version = "0.5.5" 3886 | source = "registry+https://github.com/rust-lang/crates.io-index" 3887 | checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" 3888 | 3889 | [[package]] 3890 | name = "wyz" 3891 | version = "0.5.1" 3892 | source = "registry+https://github.com/rust-lang/crates.io-index" 3893 | checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" 3894 | dependencies = [ 3895 | "tap", 3896 | ] 3897 | 3898 | [[package]] 3899 | name = "yoke" 3900 | version = "0.7.5" 3901 | source = "registry+https://github.com/rust-lang/crates.io-index" 3902 | checksum = "120e6aef9aa629e3d4f52dc8cc43a015c7724194c97dfaf45180d2daf2b77f40" 3903 | dependencies = [ 3904 | "serde", 3905 | "stable_deref_trait", 3906 | "yoke-derive", 3907 | "zerofrom", 3908 | ] 3909 | 3910 | [[package]] 3911 | name = "yoke-derive" 3912 | version = "0.7.5" 3913 | source = "registry+https://github.com/rust-lang/crates.io-index" 3914 | checksum = "2380878cad4ac9aac1e2435f3eb4020e8374b5f13c296cb75b4620ff8e229154" 3915 | dependencies = [ 3916 | "proc-macro2", 3917 | "quote", 3918 | "syn 2.0.89", 3919 | "synstructure", 3920 | ] 3921 | 3922 | [[package]] 3923 | name = "zerocopy" 3924 | version = "0.7.35" 3925 | source = "registry+https://github.com/rust-lang/crates.io-index" 3926 | checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" 3927 | dependencies = [ 3928 | "byteorder", 3929 | "zerocopy-derive", 3930 | ] 3931 | 3932 | [[package]] 3933 | name = "zerocopy-derive" 3934 | version = "0.7.35" 3935 | source = "registry+https://github.com/rust-lang/crates.io-index" 3936 | checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" 3937 | dependencies = [ 3938 | "proc-macro2", 3939 | "quote", 3940 | "syn 2.0.89", 3941 | ] 3942 | 3943 | [[package]] 3944 | name = "zerofrom" 3945 | version = "0.1.5" 3946 | source = "registry+https://github.com/rust-lang/crates.io-index" 3947 | checksum = "cff3ee08c995dee1859d998dea82f7374f2826091dd9cd47def953cae446cd2e" 3948 | dependencies = [ 3949 | "zerofrom-derive", 3950 | ] 3951 | 3952 | [[package]] 3953 | name = "zerofrom-derive" 3954 | version = "0.1.5" 3955 | source = "registry+https://github.com/rust-lang/crates.io-index" 3956 | checksum = "595eed982f7d355beb85837f651fa22e90b3c044842dc7f2c2842c086f295808" 3957 | dependencies = [ 3958 | "proc-macro2", 3959 | "quote", 3960 | "syn 2.0.89", 3961 | "synstructure", 3962 | ] 3963 | 3964 | [[package]] 3965 | name = "zeroize" 3966 | version = "1.8.1" 3967 | source = "registry+https://github.com/rust-lang/crates.io-index" 3968 | checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" 3969 | 3970 | [[package]] 3971 | name = "zerovec" 3972 | version = "0.10.4" 3973 | source = "registry+https://github.com/rust-lang/crates.io-index" 3974 | checksum = "aa2b893d79df23bfb12d5461018d408ea19dfafe76c2c7ef6d4eba614f8ff079" 3975 | dependencies = [ 3976 | "yoke", 3977 | "zerofrom", 3978 | "zerovec-derive", 3979 | ] 3980 | 3981 | [[package]] 3982 | name = "zerovec-derive" 3983 | version = "0.10.3" 3984 | source = "registry+https://github.com/rust-lang/crates.io-index" 3985 | checksum = "6eafa6dfb17584ea3e2bd6e76e0cc15ad7af12b09abdd1ca55961bed9b1063c6" 3986 | dependencies = [ 3987 | "proc-macro2", 3988 | "quote", 3989 | "syn 2.0.89", 3990 | ] 3991 | 3992 | [[package]] 3993 | name = "zip" 3994 | version = "2.2.1" 3995 | source = "registry+https://github.com/rust-lang/crates.io-index" 3996 | checksum = "99d52293fc86ea7cf13971b3bb81eb21683636e7ae24c729cdaf1b7c4157a352" 3997 | dependencies = [ 3998 | "arbitrary", 3999 | "crc32fast", 4000 | "crossbeam-utils", 4001 | "displaydoc", 4002 | "flate2", 4003 | "indexmap", 4004 | "memchr", 4005 | "thiserror 2.0.3", 4006 | "zopfli", 4007 | ] 4008 | 4009 | [[package]] 4010 | name = "zopfli" 4011 | version = "0.8.1" 4012 | source = "registry+https://github.com/rust-lang/crates.io-index" 4013 | checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946" 4014 | dependencies = [ 4015 | "bumpalo", 4016 | "crc32fast", 4017 | "lockfree-object-pool", 4018 | "log", 4019 | "once_cell", 4020 | "simd-adler32", 4021 | ] 4022 | 4023 | [[package]] 4024 | name = "zstd" 4025 | version = "0.13.2" 4026 | source = "registry+https://github.com/rust-lang/crates.io-index" 4027 | checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" 4028 | dependencies = [ 4029 | "zstd-safe", 4030 | ] 4031 | 4032 | [[package]] 4033 | name = "zstd-safe" 4034 | version = "7.2.1" 4035 | source = "registry+https://github.com/rust-lang/crates.io-index" 4036 | checksum = "54a3ab4db68cea366acc5c897c7b4d4d1b8994a9cd6e6f841f8964566a419059" 4037 | dependencies = [ 4038 | "zstd-sys", 4039 | ] 4040 | 4041 | [[package]] 4042 | name = "zstd-sys" 4043 | version = "2.0.13+zstd.1.5.6" 4044 | source = "registry+https://github.com/rust-lang/crates.io-index" 4045 | checksum = "38ff0f21cfee8f97d94cef41359e0c89aa6113028ab0291aa8ca0038995a95aa" 4046 | dependencies = [ 4047 | "cc", 4048 | "pkg-config", 4049 | ] 4050 | 4051 | [[package]] 4052 | name = "zune-core" 4053 | version = "0.4.12" 4054 | source = "registry+https://github.com/rust-lang/crates.io-index" 4055 | checksum = "3f423a2c17029964870cfaabb1f13dfab7d092a62a29a89264f4d36990ca414a" 4056 | 4057 | [[package]] 4058 | name = "zune-inflate" 4059 | version = "0.2.54" 4060 | source = "registry+https://github.com/rust-lang/crates.io-index" 4061 | checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" 4062 | dependencies = [ 4063 | "simd-adler32", 4064 | ] 4065 | 4066 | [[package]] 4067 | name = "zune-jpeg" 4068 | version = "0.4.13" 4069 | source = "registry+https://github.com/rust-lang/crates.io-index" 4070 | checksum = "16099418600b4d8f028622f73ff6e3deaabdff330fb9a2a131dea781ee8b0768" 4071 | dependencies = [ 4072 | "zune-core", 4073 | ] 4074 | --------------------------------------------------------------------------------