httplz 0.0.0

A sans-io, no-std HTTP implementation
Documentation
//! A simple client that POSTs some data to a path
//!
//! Usage:
//! cargo run --example client -- <host> <port> <path> <data>

use std::{error::Error, io::Write, net::TcpStream};

use httplz::Lift;

pub fn main() -> Result<(), Box<dyn Error>> {
	let mut args = std::env::args().skip(1);
	let (host, port, path, data) = args
		.next()
		.and_then(|h| Some((h, args.next()?, args.next()?, args.next()?)))
		.ok_or_else(|| Box::<dyn Error>::from(String::from("Missing required argument")))?;

	let mut stream = TcpStream::connect((host.as_str(), port.parse()?))?;

	let buf = vec![0; 4096];
	let mut buf = httplz_ext::Buf::new(buf);
	let mut conn = httplz::Connection::new(httplz::Role::Client);
	let events = &[
		httplz::RequestLine {
			version: httplz::Version::HTTP1_1,
			method: "POST",
			target: &path,
		}
		.into(),
		httplz::HeaderOther::from(("Host", host.as_bytes())).into(),
		httplz::HeaderOther::from(("Accept", "*/*")).into(),
		httplz::HeaderSpecial::ContentLength(data.len()).into(),
		httplz::Event::HeadersDone,
		httplz::Event::BodyChunk(data.as_bytes()),
		httplz::Event::SendDone,
	];

	for event in events {
		if let Err(e) = conn.handle_send(event, &mut buf) {
			panic!("{e:?}");
		};
	}
	stream.write_all(buf.filled())?;

	buf.clear();
	loop {
		let data = buf.filled();
		let (d, r) = conn.handle_recv(data).lift();

		match r {
			Err(httplz::Error {
				kind: httplz::ErrorKind::NeedMoreData,
				..
			}) => {
				buf.read_from(&mut stream)?;
				continue;
			},
			Err(e) => panic!("{e:?}"),
			Ok(ev) => {
				println!("{ev}");

				if ev == httplz::Event::RecvDone {
					break;
				}
			},
		};

		let len = buf.filled().len() - d.len();
		buf.pop_front(len);
	}

	Ok(())
}