mod storage;
use crate::storage::SerializedStorage;
use anyhow::{Context, Result};
use byteorder::ReadBytesExt;
use indexmap::indexmap;
use std::{
io::{BufReader, BufWriter, Write},
net::{TcpListener, TcpStream},
};
use xbf_rs::{
prelude::*, XbfPrimitive, XbfPrimitiveMetadata, XbfStruct, XbfStructMetadata, XbfVec,
XbfVecMetadata,
};
struct DragonRider {
name: String,
age: u16,
}
impl DragonRider {
fn new(name: String, age: u16) -> Self {
Self { name, age }
}
fn into_xbf_struct(self, metadata: XbfStructMetadata) -> XbfStruct {
XbfStruct::new_unchecked(
metadata,
[
self.name.into_xbf_primitive().into_base_type(),
self.age.into_xbf_primitive().into_base_type(),
],
)
}
}
#[repr(u8)]
enum RequestType {
GetMetadataAndData = 0,
GetData,
Unknown,
}
impl From<u8> for RequestType {
fn from(value: u8) -> Self {
match value {
0 => Self::GetMetadataAndData,
1 => Self::GetData,
_ => Self::Unknown,
}
}
}
fn handle_request(stream: TcpStream, storage: &SerializedStorage) -> Result<()> {
let mut reader = BufReader::new(stream.try_clone().context("Unable to clone stream")?);
let mut writer = BufWriter::new(stream);
let request_type = reader.read_u8().context("Unable to read request type")?;
let request_type = RequestType::from(request_type);
match request_type {
RequestType::GetMetadataAndData => storage
.write_metadata(&mut writer)
.and_then(|_| storage.write_value(&mut writer)),
RequestType::GetData => storage.write_value(&mut writer),
RequestType::Unknown => {
let unknown_request_message = XbfPrimitive::String(
"Unknown request type, 0 is data, 1 is data and metadata".to_string(),
);
unknown_request_message
.get_metadata()
.serialize_primitive_metadata(&mut writer)
.and_then(|_| unknown_request_message.serialize_primitive_type(&mut writer))
}
}
.context("Unable to write response")?;
writer.flush().context("Unable to flush response")
}
fn main() -> Result<()> {
let dragon_riders_storage = {
let dragon_rider_metadata = XbfStructMetadata::new(
"DragonRider",
indexmap! {
"name" => XbfPrimitiveMetadata::String.into(),
"age" => XbfPrimitiveMetadata::U16.into(),
},
);
let dragon_riders = [
DragonRider::new("Eragon".to_string(), 16),
DragonRider::new("Arya".to_string(), 103),
DragonRider::new("Galbatorix".to_string(), 133),
]
.map(|dragon_rider| dragon_rider.into_xbf_struct(dragon_rider_metadata.clone()));
SerializedStorage::new(XbfVec::new_unchecked(
XbfVecMetadata::new(dragon_rider_metadata),
dragon_riders,
))
};
let stream = TcpListener::bind("127.0.0.1:6969").context("Unable to bind tcp listener")?;
for stream in stream.incoming() {
let stream_result = stream
.context("Unable to accept connection")
.and_then(|stream| handle_request(stream, &dragon_riders_storage));
if let Err(e) = stream_result {
eprintln!("{}", e);
}
}
Ok(())
}