chore: fix unused imports and warnings

This commit is contained in:
Andrea Toska 2025-04-26 21:03:07 +02:00
commit 37a2329c6c
No known key found for this signature in database
GPG key ID: 5B3C83807CCBE9A2
20 changed files with 73 additions and 112 deletions

1
Cargo.lock generated
View file

@ -1828,6 +1828,7 @@ dependencies = [
"base64", "base64",
"bytemuck", "bytemuck",
"reqwest", "reqwest",
"tokio",
] ]
[[package]] [[package]]

View file

@ -7,6 +7,4 @@ edition = "2024"
base64 = "0.22.1" base64 = "0.22.1"
bytemuck = { version = "1.21.0", features = ["derive"] } bytemuck = { version = "1.21.0", features = ["derive"] }
reqwest = "0.12.12" reqwest = "0.12.12"
tokio = { version = "1.43.0", features = ["macros"] }
[dev-dependencies]
tokio = { version = "1.43.0", features = ["macros"] }

View file

@ -1,6 +1,5 @@
use std::ops::Index;
use std::str::FromStr; use std::str::FromStr;
use bytemuck::{from_bytes, try_from_bytes, Pod, Zeroable}; use bytemuck::{try_from_bytes, Pod, Zeroable};
use base64::Engine; use base64::Engine;
use base64::prelude::BASE64_STANDARD; use base64::prelude::BASE64_STANDARD;
use reqwest::Url; use reqwest::Url;
@ -73,7 +72,10 @@ pub async fn get_image_tga(data: &str) -> Option<Vec<u8>>{
#[cfg(test)] #[cfg(test)]
mod test{ mod test{
#[tokio::test] use std::fs;
use crate::get_image_png;
#[tokio::test]
async fn test_image_get(){ async fn test_image_get(){
let image = get_image_png("AAEAQDrPvmeBxJIQ3cL/BYp4iCWDvgAA8FVEAEoATQByAFQAVgAAAGgAZQByAAB/BAApBBpK4xiXEqQMAhgXbAoACClQQkhQTQBFAAAALQBTAHcAaQB0AGMAaAAAAMqP").await.unwrap(); let image = get_image_png("AAEAQDrPvmeBxJIQ3cL/BYp4iCWDvgAA8FVEAEoATQByAFQAVgAAAGgAZQByAAB/BAApBBpK4xiXEqQMAhgXbAoACClQQkhQTQBFAAAALQBTAHcAaQB0AGMAaAAAAMqP").await.unwrap();

View file

@ -1,18 +1,17 @@
use std::io::Write; use std::io::Write;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use argon2::{Algorithm, Argon2, PasswordHash, PasswordHasher, PasswordVerifier}; // Don't import until required.
use argon2::password_hash::rand_core::OsRng; // use argon2::{Algorithm, Argon2, PasswordHash, PasswordHasher, PasswordVerifier};
use argon2::password_hash::SaltString; // use argon2::password_hash::rand_core::OsRng;
// use argon2::password_hash::SaltString;
use base64::Engine; use base64::Engine;
use base64::prelude::BASE64_STANDARD; use base64::prelude::BASE64_STANDARD;
use bytemuck::bytes_of; use bytemuck::bytes_of;
use chrono::{NaiveDate, NaiveDateTime, NaiveTime, TimeZone, Utc}; use chrono::{NaiveDate, NaiveDateTime, Utc};
use log::{error, warn};
use rocket::http::Status; use rocket::http::Status;
use rocket::{async_trait, Request}; use rocket::{async_trait, Request};
use rocket::request::{FromRequest, Outcome}; use rocket::request::{FromRequest, Outcome};
use sha2::{Digest, Sha256}; use sha2::{Digest, Sha256};
use sha2::digest::FixedOutput;
use crate::error::{Error, Errors}; use crate::error::{Error, Errors};
use crate::nnid::oauth::TokenData; use crate::nnid::oauth::TokenData;
use crate::Pool; use crate::Pool;
@ -35,15 +34,6 @@ const INVALID_TOKEN_ERRORS: Errors<'static> = Errors{
] ]
}; };
const INVALID_TOKEN_ERRORS_DBG: Errors<'static> = Errors{
error: &[
Error{
message: "Test err 1",
code: "0305"
}
]
};
// optimization note: add token caching // optimization note: add token caching
#[derive(Debug)] #[derive(Debug)]
pub struct User { pub struct User {
@ -112,8 +102,6 @@ pub fn generate_password(pid: i32, cleartext_password: &str) -> Option<String>{
pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<User> { pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<User> {
println!("Received token (base64): {:?}", token);
let data = match BASE64_STANDARD.decode(&token) { let data = match BASE64_STANDARD.decode(&token) {
Ok(d) => d, Ok(d) => d,
Err(e) => { Err(e) => {
@ -121,7 +109,6 @@ pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<Use
return None; return None;
} }
}; };
println!("Decoded base64 bytes: {:?}", data);
let decoded_basic_token = match String::from_utf8(data) { let decoded_basic_token = match String::from_utf8(data) {
Ok(s) => s, Ok(s) => s,
@ -130,7 +117,6 @@ pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<Use
return None; return None;
} }
}; };
println!("Decoded basic auth token string: {:?}", decoded_basic_token);
let (login_username, login_password) = match decoded_basic_token.split_once(' ') { let (login_username, login_password) = match decoded_basic_token.split_once(' ') {
Some(parts) => parts, Some(parts) => parts,
@ -139,8 +125,6 @@ pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<Use
return None; return None;
} }
}; };
println!("Parsed login_username: {:?}", login_username);
println!("Parsed login_password: {:?}", login_password);
let user_result = sqlx::query_as!( let user_result = sqlx::query_as!(
User, User,
@ -148,7 +132,7 @@ pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<Use
login_username login_username
).fetch_one(connection).await; ).fetch_one(connection).await;
let mut user = match user_result { let user = match user_result {
Ok(u) => u, Ok(u) => u,
Err(e) => { Err(e) => {
println!("Failed to fetch user from database: {:?}", e); println!("Failed to fetch user from database: {:?}", e);
@ -157,13 +141,10 @@ pub async fn read_basic_auth_token(connection: &Pool, token: &str) -> Option<Use
}; };
let password_valid = user.verify_cleartext_password(&login_password); let password_valid = user.verify_cleartext_password(&login_password);
println!("Password verification result: {:?}", password_valid);
if password_valid == Some(true) { if password_valid == Some(true) {
println!("Password verification succeeded");
Some(user) Some(user)
} else { } else {
println!("Password verification failed");
None None
} }
} }
@ -183,7 +164,7 @@ pub async fn read_bearer_auth_token(connection: &Pool, token: &str) -> Option<Us
return None return None
} }
let mut user = sqlx::query_as!( let user = sqlx::query_as!(
User, User,
"SELECT * FROM users WHERE pid = $1", "SELECT * FROM users WHERE pid = $1",
token_info.pid token_info.pid
@ -247,7 +228,7 @@ impl<'r, const FORCE_BEARER_AUTH: bool> FromRequest<'r> for Auth<FORCE_BEARER_AU
}; };
let Some(user) = user else { let Some(user) = user else {
return Outcome::Error((Status::BadRequest, INVALID_TOKEN_ERRORS_DBG)); return Outcome::Error((Status::BadRequest, INVALID_TOKEN_ERRORS));
}; };
Outcome::Success(Self(user)) Outcome::Success(Self(user))

View file

@ -1 +1,2 @@
use serde::{Deserialize, Serialize}; // use serde::{Deserialize, Serialize};
// Don't generate warnings for no reason, DJ. :P

View file

@ -1,9 +1,6 @@
use std::marker::PhantomData;
use rocket::{Request, Response}; use rocket::{Request, Response};
use rocket::http::{Header, Status}; use rocket::http::Header;
use rocket::response::Responder; use rocket::response::Responder;
use crate::error::Errors;
use crate::xml::Xml;
pub struct Ds<T>(pub T); pub struct Ds<T>(pub T);

View file

@ -1,11 +1,8 @@
use log::error;
use rocket::http::Status; use rocket::http::Status;
use rocket::{Request, Response}; use rocket::{Request, Response};
use rocket::response::content::RawXml;
use rocket::response::Responder; use rocket::response::Responder;
use rocket::serde::Serialize; use rocket::serde::Serialize;
use crate::nnid::timezones::Timezone; use crate::xml::Xml;
use crate::xml::{serialize_with_version, Xml};
#[derive(Serialize, Debug)] #[derive(Serialize, Debug)]
pub struct Error<'a>{ pub struct Error<'a>{

View file

@ -1,9 +1,8 @@
use std::fmt::Display;
use chrono::NaiveDateTime; use chrono::NaiveDateTime;
use juniper::{graphql_object, EmptyMutation, EmptySubscription, GraphQLObject, RootNode, ScalarValue}; use juniper::{graphql_object, EmptyMutation, EmptySubscription, GraphQLObject, RootNode};
use rocket::response::content::RawHtml; use rocket::response::content::RawHtml;
use rocket::State; use rocket::State;
use crate::account::account::{read_basic_auth_token, read_bearer_auth_token}; // use crate::account::account::{read_basic_auth_token, read_bearer_auth_token};
use crate::nnid::oauth::TokenData; use crate::nnid::oauth::TokenData;
use crate::Pool; use crate::Pool;

View file

@ -1,16 +1,12 @@
use std::env; use std::env;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4}; use std::net::{IpAddr, Ipv4Addr, SocketAddr};
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH}; use std::time::{SystemTime, UNIX_EPOCH};
use dotenvy::dotenv; use dotenvy::dotenv;
use juniper::{EmptyMutation, EmptySubscription}; use juniper::{EmptyMutation, EmptySubscription};
use log::info;
use rocket::fairing::AdHoc; use rocket::fairing::AdHoc;
use rocket::futures::FutureExt; use rocket::http::{ContentType, Header, Status};
use rocket::http::Header; use rocket::{catch, catchers, routes, Request};
use rocket::routes; use rocket::response::content::RawXml;
use sqlx::Postgres; use sqlx::Postgres;
use sqlx::postgres::PgPoolOptions; use sqlx::postgres::PgPoolOptions;
use tonic::transport::Server; use tonic::transport::Server;
@ -23,7 +19,7 @@ mod account;
mod error; mod error;
mod dsresponse; mod dsresponse;
mod data_wrapper; mod data_wrapper;
#[deprecated] // #[deprecated]
mod grpc; mod grpc;
mod graphql; mod graphql;
mod email; mod email;
@ -62,6 +58,26 @@ async fn start_grpc(){
} }
#[catch(404)]
fn not_found(_req: &Request) -> (Status, (ContentType, RawXml<&'static str>)) {
(
Status::NotFound,
(
ContentType::XML,
RawXml(
r#"<?xml version="1.0"?>
<errors>
<error>
<cause/>
<code>0008</code>
<message>Not found</message>
</error>
</errors>"#,
),
),
)
}
#[rocket::launch] #[rocket::launch]
async fn launch() -> _ { async fn launch() -> _ {
dotenv().ok(); dotenv().ok();
@ -116,6 +132,7 @@ async fn launch() -> _ {
nnid::people::get_own_profile, nnid::people::get_own_profile,
nnid::people::get_device_owner, nnid::people::get_device_owner,
nnid::people::get_own_device, nnid::people::get_own_device,
nnid::people::change_mii,
nnid::oauth::generate_token::generate_token, nnid::oauth::generate_token::generate_token,
nnid::provider::get_nex_token, nnid::provider::get_nex_token,
nnid::provider::get_service_token, nnid::provider::get_service_token,
@ -126,4 +143,5 @@ async fn launch() -> _ {
graphql::get_graphql, graphql::get_graphql,
graphql::post_graphql, graphql::post_graphql,
]) ])
.register("/", catchers![not_found])
} }

View file

@ -1,11 +1,9 @@
use std::{env, fs, io}; use std::{env, io};
use rocket::fs::NamedFile; use rocket::fs::NamedFile;
use rocket::get; use rocket::get;
use rocket::response::content::RawXml; use rocket::response::content::RawXml;
use tokio::fs::try_exists; use tokio::fs::try_exists;
use crate::dsresponse::Ds; use crate::dsresponse::Ds;
use crate::nnid::devices::Device;
use crate::xml::Xml;
#[get("/v1/api/content/agreements/Nintendo-Network-EULA/<lang>/@latest")] #[get("/v1/api/content/agreements/Nintendo-Network-EULA/<lang>/@latest")]
pub async fn get_agreement(lang: &str) -> io::Result<Ds<RawXml<NamedFile>>>{ pub async fn get_agreement(lang: &str) -> io::Result<Ds<RawXml<NamedFile>>>{

View file

@ -13,7 +13,6 @@ pub fn current_device_status() -> Xml<Device>{
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::str::from_utf8;
use crate::nnid::devices::Device; use crate::nnid::devices::Device;
#[test] #[test]

View file

@ -12,7 +12,7 @@ struct MappedId {
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename = "mapped_ids")] #[serde(rename = "mapped_ids")]
struct MappedIds { pub struct MappedIds {
mapped_id: Vec<MappedId>, mapped_id: Vec<MappedId>,
} }

View file

@ -1,6 +1,6 @@
use rocket::{post, FromForm, State}; use rocket::{post, FromForm, State};
use rocket::form::Form; use rocket::form::Form;
use serde::{Deserialize, Serialize}; use serde::{Serialize};
use crate::account::account::User; use crate::account::account::User;
use crate::error::{Error, Errors}; use crate::error::{Error, Errors};
use crate::nnid::oauth::generate_token::token_type::{AUTH_REFRESH_TOKEN, AUTH_TOKEN}; use crate::nnid::oauth::generate_token::token_type::{AUTH_REFRESH_TOKEN, AUTH_TOKEN};

View file

@ -1,13 +1,8 @@
use std::env; use std::env;
use std::io::Write; use aes::{Aes128, Block};
use aes::{Aes128, Aes256, Block};
use aes::cipher::consts::{U32, U64};
use aes::cipher::{BlockDecryptMut, BlockEncryptMut, Iv, Key}; use aes::cipher::{BlockDecryptMut, BlockEncryptMut, Iv, Key};
use aes::cipher::generic_array::sequence::GenericSequence; use aes::cipher::generic_array::sequence::GenericSequence;
use bytemuck::{bytes_of, bytes_of_mut, from_bytes, from_bytes_mut, Pod, Zeroable}; use bytemuck::{bytes_of, from_bytes, Pod, Zeroable};
use chrono::NaiveTime;
use hmac::{Hmac, Mac};
use md5::Md5;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use aes::cipher::KeyIvInit; use aes::cipher::KeyIvInit;
use base64::Engine; use base64::Engine;
@ -23,26 +18,18 @@ pub struct TokenData{
pub token_id: i64 pub token_id: i64
} }
static HMAC_SECRET: Lazy<Key<HmacMd5>> = Lazy::new(||{
Key::<HmacMd5>::clone_from_slice(&hex::decode(
env::var("ACCOUNT_HMAC_SECRET").expect("hmac secret has not been set")
).expect("unable to decode ACCOUNT_HMAC_SECRET"))
});
static AES_KEY: Lazy<Key<Aes128>> = Lazy::new(||{ static AES_KEY: Lazy<Key<Aes128>> = Lazy::new(||{
Key::<Aes128>::clone_from_slice(&hex::decode( Key::<Aes128>::clone_from_slice(&hex::decode(
env::var("ACCOUNT_AES_KEY").expect("hmac secret has not been set") env::var("ACCOUNT_AES_KEY").expect("hmac secret has not been set")
).expect("unable to decode ACCOUNT_AES_KEY")) ).expect("unable to decode ACCOUNT_AES_KEY"))
}); });
type HmacMd5 = Hmac<Md5>;
type Aes128CbcEnc = cbc::Encryptor<Aes128>; type Aes128CbcEnc = cbc::Encryptor<Aes128>;
type Aes128CbcDec = cbc::Decryptor<Aes128>; type Aes128CbcDec = cbc::Decryptor<Aes128>;
impl TokenData{ impl TokenData{
pub fn decode(token: &str) -> Option<Self>{ pub fn decode(token: &str) -> Option<Self>{
let mut data = BASE64_STANDARD.decode(token).ok()?; let data = BASE64_STANDARD.decode(token).ok()?;
let data: [u8; 16] = data.try_into().ok()?; let data: [u8; 16] = data.try_into().ok()?;
@ -82,7 +69,7 @@ impl TokenData{
#[cfg(test)] #[cfg(test)]
mod test{ mod test{
use std::env; use std::env;
use crate::nnid::oauth::{TokenData, AES_KEY}; use crate::nnid::oauth::{TokenData};
#[test] #[test]
fn test_encode_decode(){ fn test_encode_decode(){

View file

@ -1,13 +1,10 @@
use std::env; use std::env;
use std::io::Cursor; use chrono::{NaiveDate, NaiveDateTime};
use chrono::{NaiveDate, NaiveDateTime, NaiveTime};
use gxhash::{gxhash32, gxhash64}; use gxhash::{gxhash32, gxhash64};
use minio::s3::args::PutObjectArgs; use minio::s3::builders::{ObjectContent};
use minio::s3::builders::{ObjectContent, SegmentedBytes};
use minio::s3::client::ClientBuilder; use minio::s3::client::ClientBuilder;
use minio::s3::creds::StaticProvider; use minio::s3::creds::StaticProvider;
use minio::s3::http::BaseUrl; use minio::s3::http::BaseUrl;
use minio::s3::utils::crc32;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rocket::{get, post, put, State}; use rocket::{get, post, put, State};
use rocket::serde::{Deserialize, Serialize}; use rocket::serde::{Deserialize, Serialize};
@ -15,7 +12,7 @@ use crate::account::account::{generate_password, Auth, User};
use crate::dsresponse::Ds; use crate::dsresponse::Ds;
use crate::error::Errors; use crate::error::Errors;
use crate::nnid::pid_distribution::next_pid; use crate::nnid::pid_distribution::next_pid;
use crate::nnid::timezones::{OFFSET_FROM_TIMEZONE, ZONE_TO_TIMEZONES}; use crate::nnid::timezones::{OFFSET_FROM_TIMEZONE};
use crate::Pool; use crate::Pool;
use crate::xml::{Xml, YesNoVal}; use crate::xml::{Xml, YesNoVal};
use crate::email::send_verification_email; use crate::email::send_verification_email;
@ -191,10 +188,10 @@ pub async fn create_account(database: &State<Pool>, data: Xml<AccountCreationDat
) )
} }
#[derive(Serialize)] // #[derive(Serialize)]
struct DevAttr{ // struct DevAttr{
//
} // }
#[derive(Serialize)] #[derive(Serialize)]
struct EmailInfoOwnProfileData{ struct EmailInfoOwnProfileData{
@ -240,7 +237,7 @@ struct MiiDataOwnProfileData{
#[derive(Serialize)] #[derive(Serialize)]
#[serde(rename(serialize = "person"))] #[serde(rename(serialize = "person"))]
struct GetOwnProfileData{ pub struct GetOwnProfileData{
active_flag: YesNoVal, active_flag: YesNoVal,
birth_date: NaiveDate, birth_date: NaiveDate,
country: String, country: String,
@ -278,7 +275,7 @@ fn build_own_profile(user: User) -> Ds<Xml<GetOwnProfileData>> {
let User { let User {
username, username,
pid, pid,
account_level, // account_level,
mii_data, mii_data,
gender, gender,
birthdate, birthdate,
@ -292,6 +289,7 @@ fn build_own_profile(user: User) -> Ds<Xml<GetOwnProfileData>> {
marketing_allowed, marketing_allowed,
off_device_allowed, off_device_allowed,
region, region,
// verification_code,
.. ..
} = user.into(); } = user.into();

View file

@ -1,8 +1,6 @@
use rocket::{get, State}; use rocket::{get, State};
use sqlx::Row;
use crate::error::{Error, Errors}; use crate::error::{Error, Errors};
use crate::Pool; use crate::Pool;
use crate::xml::Xml;
#[get("/v1/api/people/<username>")] #[get("/v1/api/people/<username>")]

View file

@ -1,21 +1,14 @@
use std::net::Ipv4Addr; use std::net::Ipv4Addr;
use std::str::FromStr;
use rocket::{get, State}; use rocket::{get, State};
use serde::Serialize; use serde::Serialize;
use sqlx::types::ipnetwork::IpNetwork::V4; use sqlx::types::ipnetwork::IpNetwork::V4;
use crate::account::account::Auth; use crate::account::account::Auth;
use crate::error::{Error, Errors}; use crate::error::{Error, Errors};
use crate::nnid::oauth::generate_token::{create_token, TokenRequestReturnData}; use crate::nnid::oauth::generate_token::{create_token};
use crate::nnid::oauth::generate_token::token_type::NEX_TOKEN; use crate::nnid::oauth::generate_token::token_type::NEX_TOKEN;
use crate::nnid::provider::Test::{A, B};
use crate::Pool; use crate::Pool;
use crate::xml::Xml; use crate::xml::Xml;
enum Test{
A(String),
B(i32)
}
const NO_IPV4_ERROR: Errors = Errors{ const NO_IPV4_ERROR: Errors = Errors{
error: &[ error: &[
Error{ Error{

View file

@ -1,4 +1,4 @@
use rocket::{get, State, post, FromForm, put}; use rocket::{State, post, FromForm, put};
use crate::Pool; use crate::Pool;
use rocket::form::Form; use rocket::form::Form;
use crate::email::send_verification_email; use crate::email::send_verification_email;
@ -15,7 +15,7 @@ const BAD_CODE_ERROR: Errors = Errors{
}; };
#[derive(FromForm)] #[derive(FromForm)]
struct ValidateEmailInput{ pub struct ValidateEmailInput{
email: String, email: String,
} }
#[post("/v1/api/support/validate/email", data="<data>")] #[post("/v1/api/support/validate/email", data="<data>")]

View file

@ -3,8 +3,7 @@ use std::{env, fs};
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use rocket::get; use rocket::get;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::from_slice; use crate::xml::{Xml};
use crate::xml::{serialize_with_version, Xml};
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
#[serde(rename(serialize = "timezone"))] #[serde(rename(serialize = "timezone"))]

View file

@ -1,5 +1,4 @@
use std::fmt::Formatter; use std::fmt::Formatter;
use std::io::Cursor;
use std::ops::{Deref, DerefMut}; use std::ops::{Deref, DerefMut};
use std::result; use std::result;
use rocket::http::Status; use rocket::http::Status;
@ -8,15 +7,11 @@ use rocket::response::Responder;
use serde::{Deserialize, Deserializer, Serialize}; use serde::{Deserialize, Deserializer, Serialize};
use rocket::response::Result; use rocket::response::Result;
use log::error; use log::error;
use quick_xml::events::{BytesDecl, Event};
use quick_xml::se::Serializer; use quick_xml::se::Serializer;
use quick_xml::{DeError, SeError}; use quick_xml::{DeError, SeError};
use rocket::data::{ByteUnit, FromData, Outcome}; use rocket::data::{ByteUnit, FromData, Outcome};
use rocket::response::content::RawXml; use rocket::response::content::RawXml;
use rocket::response::status::BadRequest;
use serde::__private::de::UntaggedUnitVisitor;
use serde::de::{DeserializeOwned, Error, Visitor}; use serde::de::{DeserializeOwned, Error, Visitor};
use thiserror::Error;
pub fn serialize_with_version(serializable: &impl Serialize) -> result::Result<Box<str>, SeError>{ pub fn serialize_with_version(serializable: &impl Serialize) -> result::Result<Box<str>, SeError>{
let mut write_dest = "<?xml version=\"1.0\"?>".to_owned(); let mut write_dest = "<?xml version=\"1.0\"?>".to_owned();
@ -61,7 +56,7 @@ impl<'r, 'o: 'r, T: Serialize> Responder<'r, 'o> for Xml<T>{
impl<'r, T: DeserializeOwned> FromData<'r> for Xml<T>{ impl<'r, T: DeserializeOwned> FromData<'r> for Xml<T>{
type Error = Option<DeError>; type Error = Option<DeError>;
async fn from_data(req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> { async fn from_data(_req: &'r Request<'_>, data: Data<'r>) -> Outcome<'r, Self> {
let data = data.open(1 * ByteUnit::MB); let data = data.open(1 * ByteUnit::MB);
let Ok(data) = data.into_string().await else { let Ok(data) = data.into_string().await else {
@ -83,9 +78,9 @@ pub struct YesNoVal(pub bool);
struct YesNoVisitor; struct YesNoVisitor;
#[derive(Debug, Error)] // #[derive(Debug, Error)]
#[error("did not find Y or N")] // #[error("did not find Y or N")]
struct NotYNError; // struct NotYNError;