A lot of stuff, too lazy to name it all

This commit is contained in:
nm17 2023-06-30 17:20:34 +04:00
parent ceadd2d76d
commit 83d712b930
15 changed files with 273 additions and 0 deletions

0
src/hashes.rs Normal file
View file

16
src/protocol/error.rs Normal file
View file

@ -0,0 +1,16 @@
use std::fmt::{Display, Formatter};
use std::num::ParseFloatError;
use nom::error::VerboseError;
use thiserror::Error as ThisError;
#[derive(Debug, ThisError)]
pub enum Error<I: std::fmt::Debug> {
#[error("Oops it blew up")]
NomError(#[from] nom::Err<VerboseError<I>>),
#[error("Oops it blew up")]
TimestampParseError(ParseFloatError),
#[error("Oops it blew up")]
UnknownUnit(I)
}

0
src/protocol/mod.rs Normal file
View file

View file

@ -0,0 +1,42 @@
use std::borrow::Cow;
use std::collections::HashSet;
use std::hash::{Hash, Hasher};
use hifitime::Epoch;
use rust_decimal::Decimal;
use crate::hashes::SupportedUnit;
#[derive(Debug, Clone)]
pub struct NarodMonValues<'a> {
pub mac: Cow<'a, str>,
pub value: Decimal,
pub time: Option<Epoch>,
pub unit: Option<SupportedUnit>,
pub name: Option<Cow<'a, str>>,
}
impl<'a> Hash for NarodMonValues<'a> {
fn hash<H: Hasher>(&self, state: &mut H) {
self.mac.hash(state);
}
}
impl<'a> PartialEq for NarodMonValues<'a> {
fn eq(&self, other: &Self) -> bool {
self.mac == other.mac
}
}
impl<'a> Eq for NarodMonValues<'a> {
}
#[derive(Debug, Clone, Default)]
pub struct NarodMonPacket<'a> {
pub mac: [u8; 6],
pub name: Option<Cow<'a, str>>,
pub values: HashSet<NarodMonValues<'a>>,
pub owner: Option<Cow<'a, str>>,
pub lat: Option<Decimal>,
pub lon: Option<Decimal>,
pub alt: Option<Decimal>
}

0
src/protocol/parser.rs Normal file
View file

0
src/protocol/server.rs Normal file
View file

View file

@ -0,0 +1,88 @@
use std::borrow::Cow;
use axum::headers::HeaderValue;
use axum::http::StatusCode;
use axum::Json;
use axum::response::{IntoResponse, Response};
use fred::prelude::*;
use rust_decimal::Decimal;
use serde_json::json;
use thiserror::Error;
use ufmt::derive::uDebug;
#[derive(Debug, Error)]
pub enum AppError {
#[error("IDK")]
JsonError(#[from] serde_json::Error),
#[error("IDK")]
ServerRedisError(#[from] RedisError),
#[error("Fuck")]
UnknownMethod(String),
#[error("Fuck")]
RequestTooLarge,
#[error("Fuck")]
UnitValidationFailed {
max: Option<Decimal>,
min: Option<Decimal>
}
}
impl IntoResponse for AppError {
fn into_response(self) -> Response {
let (status, error_message) = match self {
AppError::JsonError(_) => {
(StatusCode::BAD_REQUEST, "Invalid JSON")
},
AppError::UnknownMethod(_) => {
(StatusCode::BAD_REQUEST, "Unknown command")
},
AppError::UnitValidationFailed { .. } => {
(StatusCode::BAD_REQUEST, "Unknown command")
},
AppError::RequestTooLarge => {
(StatusCode::PAYLOAD_TOO_LARGE, "Request is too large")
},
AppError::ServerRedisError(_) => {
(StatusCode::INTERNAL_SERVER_ERROR, "Internal server error")
}
};
let body = Json(json!({
"errno": status.as_u16(),
"error": error_message,
}));
let mut resp = (status, body).into_response();
let headers = resp.headers_mut();
let error_as_string= format!("{:?}", &self);
match self {
AppError::JsonError(json_err) => {
headers.insert("X-Error-Line", HeaderValue::from(json_err.line()));
headers.insert("X-Error-Column", HeaderValue::from(json_err.column()));
headers.insert("X-Error-Description", HeaderValue::try_from(json_err.to_string().escape_default().collect::<String>()).unwrap());
},
AppError::UnknownMethod(method) => {
headers.insert("X-Unknown-Cmd", HeaderValue::try_from(method.escape_default().collect::<String>()).unwrap());
},
AppError::RequestTooLarge => {
headers.insert("X-Max-Request-Size", HeaderValue::try_from("10 KiB = 10240 bytes").unwrap());
},
_ => {}
};
if cfg!(debug_assertions) {
headers.insert("X-Full-Error", HeaderValue::try_from(error_as_string).unwrap());
}
resp
}
}

18
src/web_server/mod.rs Normal file
View file

@ -0,0 +1,18 @@
use std::time::Duration;
use tokio;
use axum::{
routing::get,
Router,
};
use axum::error_handling::{HandleError, HandleErrorLayer};
use axum::http::StatusCode;
use crate::server::old_app_api::old_api_handler;
pub mod old_app_api;
#[derive(Clone)]
struct NMAppState {
redis_client: RedisClient
}
async fn main()

View file

@ -0,0 +1,35 @@
use std::borrow::Cow;
use axum::body::{Body, Bytes, HttpBody};
use axum::http::Request;
use axum::Json;
use axum::response::{IntoResponse, Response};
use nom::AsBytes;
use serde_json::Value;
use crate::server::old_app_api::app_error::AppError;
use crate::server::old_app_api::handlers::app_init;
use crate::server::old_app_api::types::{AppInitRequest, MandatoryParams};
pub async fn old_api_handler(
body_bytes: Bytes,
) -> Result<impl IntoResponse, AppError> {
if body_bytes.len() > 10 * 1024 { // 10 KiB
return Err(AppError::RequestTooLarge)
}
let mandatory_params: MandatoryParams<'_> = serde_json::from_slice(body_bytes.as_bytes())?;
return match mandatory_params.cmd.as_ref() {
"appInit" => {
let body: AppInitRequest = serde_json::from_slice(body_bytes.as_bytes())?;
Ok(app_init(body).await)
}
_ => {
Err(AppError::UnknownMethod(mandatory_params.cmd.to_string()))
}
}
//Ok("fuck")
}

View file

@ -0,0 +1,17 @@
use axum::body::Body;
use axum::extract::State;
use axum::http::Request;
use axum::Json;
use axum::response::IntoResponse;
use serde_json::Value as JsonValue;
use crate::server::old_app_api::types::AppInitRequest;
use heapless::String as HeaplessString;
use ufmt::uwrite;
pub async fn app_init(body: AppInitRequest<'_>, State(appState): State<>) -> impl IntoResponse {
"Hello, World!"
}

View file

@ -0,0 +1,10 @@
mod methods;
use std::collections::HashMap;
use axum::Json;
use axum::response::IntoResponse;
use phf::phf_map;
use serde::{Deserialize, Serialize};
use crate::hashes::SupportedUnit;
pub use methods::*;

View file

@ -0,0 +1,7 @@
mod types;
mod handlers;
mod config_app;
mod app_error;
pub use config_app::old_api_handler;

View file

@ -0,0 +1,40 @@
use std::borrow::Cow;
use serde::{Deserialize, Deserializer, Serialize};
use crate::hashes::SupportedUnit;
// fn<'de, D>(D) -> Result<T, D::Error> where D: Deserializer<'de>
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AppInitRequest<'a> {
#[serde(borrow)]
pub version: Cow<'a, str>,
#[serde(borrow)]
pub platform: Cow<'a, str>,
#[serde(borrow)]
pub model: Cow<'a, str>,
#[serde(borrow)]
pub width: Cow<'a, str>,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct AddLikeRequest {
pub version: u64,
}
#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct MandatoryParams<'a> {
#[serde(borrow)]
pub cmd: Cow<'a, str>,
#[serde(borrow)]
pub lang: Cow<'a, str>,
#[serde(borrow)]
pub uuid: Cow<'a, str>,
#[serde(borrow)]
pub api_key: Cow<'a, str>
}

View file

View file