work done in school

This commit is contained in:
maxstrb 2025-10-06 19:10:16 +02:00
parent 320a93118f
commit 860ddc7cf4
37 changed files with 146 additions and 18 deletions

7
Cargo.lock generated Normal file
View file

@ -0,0 +1,7 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "multiplayer-game"
version = "0.1.0"

View file

@ -1,11 +1,13 @@
use crate::shared_enums::ContentType; use crate::shared_enums::ContentType;
use std::{ use std::{
io::{self, BufRead, BufReader, Read}, io::{self, BufRead, BufReader, Read, Take},
net::TcpStream, net::TcpStream,
str::FromStr,
}; };
const MAX_LINE_WIDTH: u64 = 4096; // 4 KiB const MAX_LINE_WIDTH: u64 = 4096; // 4 KiB
const MAX_BODY_LENGTH: u64 = 8388608; // 5 MiB const MAX_BODY_LENGTH: u64 = 8388608; // 5 MiB
const MAX_HEADER_COUNT: u64 = 512;
pub struct Request { pub struct Request {
method: Method, method: Method,
@ -23,37 +25,96 @@ pub enum RequestHeader {
Other(String, String), Other(String, String),
} }
impl FromStr for RequestHeader {
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let
}
}
impl Request { impl Request {
pub fn from_bufreader(buffer: BufReader<&TcpStream>) -> io::Result<Self> { pub fn from_bufreader(buffer: BufReader<&TcpStream>) -> io::Result<Self> {
let mut first_line = Vec::<u8>::new();
let mut limited_buffer = buffer.take(MAX_LINE_WIDTH); let mut limited_buffer = buffer.take(MAX_LINE_WIDTH);
limited_buffer.read_until(b'\n', &mut first_line)?;
println!("{}", String::from_utf8_lossy(&first_line)); let first_line = Self::read_line(&mut limited_buffer)?;
first_line.clear(); let parsed_first_line = Self::parse_first_line(first_line)?;
limited_buffer.set_limit(MAX_LINE_WIDTH);
limited_buffer.read_until(b'\n', &mut first_line)?;
println!("{}", String::from_utf8_lossy(&first_line));
Ok(Self { Ok(Self {
method: Method::Get, method: parsed_first_line.0,
http_version: "HTTP/1.1".to_string(), path: parsed_first_line.1,
path: ServerPath { http_version: parsed_first_line.2,
path: vec![],
options: vec![],
},
headers: vec![], headers: vec![],
data: vec![], data: vec![],
}) })
} }
fn read_line(buffer: &mut Take<BufReader<&TcpStream>>) -> io::Result<String> {
let mut read_buffer = vec![];
buffer.set_limit(MAX_LINE_WIDTH);
buffer.read_until(b'\n', &mut read_buffer)?;
Ok(String::from_utf8_lossy(&read_buffer).to_string())
}
fn parse_first_line(line: String) -> io::Result<(Method, ServerPath, String)> {
let splitted_line: Vec<&str> = line.split_whitespace().collect();
match splitted_line.as_slice() {
[method, path, "HTTP/1.1"] => Ok((
Method::from_str(method)?,
ServerPath::from_str(path)?,
"HTTP/1.1".to_string(),
)),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
"Incorrect HTTP first line",
)),
}
}
} }
pub struct ServerPath { pub struct ServerPath {
path: Vec<String>, path: Vec<String>,
options: Vec<(String, String)>, query: Vec<(String, String)>,
}
impl FromStr for ServerPath {
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.split("?").collect::<Vec<&str>>().as_slice() {
[path, query] => {
let mut query_hashset: std::collections::hash_set::HashSet<String> =
std::collections::hash_set::HashSet::new();
let query_parsed = query
.split('&')
.filter_map(|s| match s.split('=').collect::<Vec<&str>>().as_slice() {
[parameter, value] => {
if query_hashset.contains(*parameter) {
None
} else {
query_hashset.insert(parameter.to_string());
Some((parameter.to_string(), value.to_string()))
}
}
_ => None,
})
.collect();
Ok(Self {
path: path
.split('/')
.filter(|s| !s.is_empty() && !s.starts_with('.'))
.map(|s| s.to_string())
.collect(),
query: query_parsed,
})
}
_ => Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid path")),
}
}
} }
pub enum Method { pub enum Method {
@ -67,3 +128,25 @@ pub enum Method {
Put, Put,
Trace, Trace,
} }
impl FromStr for Method {
type Err = io::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"GET" => Ok(Self::Get),
"POST" => Ok(Self::Post),
"CONNECT" => Ok(Self::Connect),
"DELETE" => Ok(Self::Delete),
"HEAD" => Ok(Self::Head),
"OPTIONS" => Ok(Self::Options),
"PATCH" => Ok(Self::Patch),
"PUT" => Ok(Self::Put),
"TRACE" => Ok(Self::Trace),
_ => Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid HTTP method",
)),
}
}
}

1
target/.rustc_info.json Normal file
View file

@ -0,0 +1 @@
{"rustc_fingerprint":12116297598588159345,"outputs":{"12016735552878863467":{"success":true,"status":"","code":0,"stdout":"rustc 1.90.0 (1159e78c4 2025-09-14)\nbinary: rustc\ncommit-hash: 1159e78c4747b02ef996e55082b704c09b970588\ncommit-date: 2025-09-14\nhost: x86_64-unknown-linux-gnu\nrelease: 1.90.0\nLLVM version: 20.1.8\n","stderr":""},"13822592305234237280":{"success":true,"status":"","code":0,"stdout":"___\nlib___.rlib\nlib___.so\nlib___.so\nlib___.a\nlib___.so\n/nix/store/ahixbqp1sm5vwzc19hz30vxvbkh7scxd-rust-default-1.90.0\noff\npacked\nunpacked\n___\ndebug_assertions\npanic=\"unwind\"\nproc_macro\ntarget_abi=\"\"\ntarget_arch=\"x86_64\"\ntarget_endian=\"little\"\ntarget_env=\"gnu\"\ntarget_family=\"unix\"\ntarget_feature=\"fxsr\"\ntarget_feature=\"sse\"\ntarget_feature=\"sse2\"\ntarget_has_atomic=\"16\"\ntarget_has_atomic=\"32\"\ntarget_has_atomic=\"64\"\ntarget_has_atomic=\"8\"\ntarget_has_atomic=\"ptr\"\ntarget_os=\"linux\"\ntarget_pointer_width=\"64\"\ntarget_vendor=\"unknown\"\nunix\n","stderr":""}},"successes":{}}

3
target/CACHEDIR.TAG Normal file
View file

@ -0,0 +1,3 @@
Signature: 8a477f597d28d172789f06886806bc55
# This file is a cache directory tag created by cargo.
# For information about cache directory tags see https://bford.info/cachedir/

0
target/debug/.cargo-lock Normal file
View file

View file

@ -0,0 +1 @@
{"rustc":16285725380928457773,"features":"[]","declared_features":"[]","target":6229377420918840853,"profile":17672942494452627365,"path":4942398508502643691,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/multiplayer-game-1e29189d72d8e29f/dep-bin-multiplayer-game","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View file

@ -0,0 +1 @@
This file has an mtime of when this was started.

View file

@ -0,0 +1,3 @@
{"$message_type":"diagnostic","message":"expected pattern, found `}`","code":null,"level":"error","spans":[{"file_name":"src/request.rs","byte_start":696,"byte_end":697,"line_start":33,"line_end":33,"column_start":5,"column_end":6,"is_primary":true,"text":[{"text":" }","highlight_start":5,"highlight_end":6}],"label":"expected pattern","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: expected pattern, found `}`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/request.rs:33:5\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m33\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m }\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mexpected pattern\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"unused variable: `req`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":351,"byte_end":354,"line_start":17,"line_end":17,"column_start":13,"column_end":16,"is_primary":true,"text":[{"text":" let req = request::Request::from_bufreader(reader)?;","highlight_start":13,"highlight_end":16}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_variables)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src/main.rs","byte_start":351,"byte_end":354,"line_start":17,"line_end":17,"column_start":13,"column_end":16,"is_primary":true,"text":[{"text":" let req = request::Request::from_bufreader(reader)?;","highlight_start":13,"highlight_end":16}],"label":null,"suggested_replacement":"_req","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused variable: `req`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:17:13\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m17\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let req = request::Request::from_bufreader(reader)?;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33mhelp: if this is intentional, prefix it with an underscore: `_req`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_variables)]` on by default\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"aborting due to 1 previous error; 1 warning emitted","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: aborting due to 1 previous error; 1 warning emitted\u001b[0m\n\n"}

View file

@ -0,0 +1 @@
This file has an mtime of when this was started.

View file

@ -0,0 +1,3 @@
{"$message_type":"diagnostic","message":"expected pattern, found `}`","code":null,"level":"error","spans":[{"file_name":"src/request.rs","byte_start":696,"byte_end":697,"line_start":33,"line_end":33,"column_start":5,"column_end":6,"is_primary":true,"text":[{"text":" }","highlight_start":5,"highlight_end":6}],"label":"expected pattern","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: expected pattern, found `}`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/request.rs:33:5\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m33\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m }\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9m^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;9mexpected pattern\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"unused variable: `req`","code":{"code":"unused_variables","explanation":null},"level":"warning","spans":[{"file_name":"src/main.rs","byte_start":351,"byte_end":354,"line_start":17,"line_end":17,"column_start":13,"column_end":16,"is_primary":true,"text":[{"text":" let req = request::Request::from_bufreader(reader)?;","highlight_start":13,"highlight_end":16}],"label":null,"suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[{"message":"`#[warn(unused_variables)]` on by default","code":null,"level":"note","spans":[],"children":[],"rendered":null},{"message":"if this is intentional, prefix it with an underscore","code":null,"level":"help","spans":[{"file_name":"src/main.rs","byte_start":351,"byte_end":354,"line_start":17,"line_end":17,"column_start":13,"column_end":16,"is_primary":true,"text":[{"text":" let req = request::Request::from_bufreader(reader)?;","highlight_start":13,"highlight_end":16}],"label":null,"suggested_replacement":"_req","suggestion_applicability":"MaybeIncorrect","expansion":null}],"children":[],"rendered":null}],"rendered":"\u001b[0m\u001b[1m\u001b[33mwarning\u001b[0m\u001b[0m\u001b[1m: unused variable: `req`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m--> \u001b[0m\u001b[0msrc/main.rs:17:13\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m\u001b[1m\u001b[38;5;12m17\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m let req = request::Request::from_bufreader(reader)?;\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33m^^^\u001b[0m\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[33mhelp: if this is intentional, prefix it with an underscore: `_req`\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m|\u001b[0m\n\u001b[0m \u001b[0m\u001b[0m\u001b[1m\u001b[38;5;12m= \u001b[0m\u001b[0m\u001b[1mnote\u001b[0m\u001b[0m: `#[warn(unused_variables)]` on by default\u001b[0m\n\n"}
{"$message_type":"diagnostic","message":"aborting due to 1 previous error; 1 warning emitted","code":null,"level":"error","spans":[],"children":[],"rendered":"\u001b[0m\u001b[1m\u001b[38;5;9merror\u001b[0m\u001b[0m\u001b[1m: aborting due to 1 previous error; 1 warning emitted\u001b[0m\n\n"}

View file

@ -0,0 +1 @@
{"rustc":16285725380928457773,"features":"[]","declared_features":"[]","target":6229377420918840853,"profile":3316208278650011218,"path":4942398508502643691,"deps":[],"local":[{"CheckDepInfo":{"dep_info":"debug/.fingerprint/multiplayer-game-32d5f81cae032a2c/dep-test-bin-multiplayer-game","checksum":false}}],"rustflags":[],"config":2069994364910194474,"compile_kind":0}

View file

@ -0,0 +1,12 @@
/home/maxag/Projects/Rust/multiplayer-game/target/debug/deps/multiplayer_game-1e29189d72d8e29f.d: src/main.rs src/request.rs src/response.rs src/shared_enums.rs Cargo.toml
/home/maxag/Projects/Rust/multiplayer-game/target/debug/deps/libmultiplayer_game-1e29189d72d8e29f.rmeta: src/main.rs src/request.rs src/response.rs src/shared_enums.rs Cargo.toml
src/main.rs:
src/request.rs:
src/response.rs:
src/shared_enums.rs:
Cargo.toml:
# env-dep:CLIPPY_ARGS=--no-deps__CLIPPY_HACKERY__
# env-dep:CLIPPY_CONF_DIR

View file

@ -0,0 +1,12 @@
/home/maxag/Projects/Rust/multiplayer-game/target/debug/deps/multiplayer_game-32d5f81cae032a2c.d: src/main.rs src/request.rs src/response.rs src/shared_enums.rs Cargo.toml
/home/maxag/Projects/Rust/multiplayer-game/target/debug/deps/libmultiplayer_game-32d5f81cae032a2c.rmeta: src/main.rs src/request.rs src/response.rs src/shared_enums.rs Cargo.toml
src/main.rs:
src/request.rs:
src/response.rs:
src/shared_enums.rs:
Cargo.toml:
# env-dep:CLIPPY_ARGS=--no-deps__CLIPPY_HACKERY__
# env-dep:CLIPPY_CONF_DIR