From 09dc73663db1683636612be717d8875a4ef9079b Mon Sep 17 00:00:00 2001 From: Tyler Clarke Date: Thu, 13 Feb 2025 15:08:59 -0500 Subject: [PATCH] SHE LIVES! --- Cargo.lock | 434 ++++++++++++++++++++++++++++++++++++- Cargo.toml | 6 +- examples/hello.rs | 14 +- generate-composer-impls.py | 2 +- src/compose.rs | 18 +- src/html.rs | 18 +- src/lib.rs | 6 +- src/output.rs | 21 ++ src/router.rs | 26 ++- src/server.rs | 46 +++- src/tuples.rs | 62 +++--- 11 files changed, 573 insertions(+), 80 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5531ebb..be687bd 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,12 +2,66 @@ # It is not intended for manual editing. version = 4 +[[package]] +name = "addr2line" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbe277e56a376000877090da837660b4427aad530e3028d44e0bffe4f89a1c1" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + +[[package]] +name = "backtrace" +version = "0.3.74" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" +dependencies = [ + "addr2line", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", + "windows-targets", +] + +[[package]] +name = "bitflags" +version = "2.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" + [[package]] name = "borrow-or-share" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3eeab4423108c5d7c744f4d234de88d18d636100093ae04caf4825134b9c3a32" +[[package]] +name = "bytes" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f61dac84819c6588b558454b194026eb1f09c293b9036ae9b159e74e73ab6cf9" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + [[package]] name = "fluent-uri" version = "0.3.2" @@ -18,6 +72,223 @@ dependencies = [ "ref-cast", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" + +[[package]] +name = "futures-task" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" + +[[package]] +name = "futures-util" +version = "0.3.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "gimli" +version = "0.31.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" + +[[package]] +name = "http" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f16ca2af56261c99fba8bac40a10251ce8188205a4c448fbb745a2e4daa76fea" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +dependencies = [ + "bytes", + "http", +] + +[[package]] +name = "http-body-util" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2d708df4e7140240a16cd6ab0ab65c972d7433ab77819ea693fde9c43811e2a" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "hyper" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc2b571658e38e0c01b1fdca3bbbe93c00d3d71693ff2770043f8c29bc7d6f80" +dependencies = [ + "bytes", + "futures-channel", + "futures-util", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "smallvec", + "tokio", +] + +[[package]] +name = "hyper-util" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +dependencies = [ + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "itoa" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d75a2a4b1b190afb6f5425f10f6a8f959d2ea0b9c2b1d79553551850539e4674" + +[[package]] +name = "libc" +version = "0.2.169" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" + +[[package]] +name = "lock_api" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" +dependencies = [ + "autocfg", + "scopeguard", +] + +[[package]] +name = "memchr" +version = "2.7.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" + +[[package]] +name = "miniz_oxide" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b3b1c9bd4fe1f0f8b387f6eb9eb3b4a1aa26185e5750efb9140301703f62cd1b" +dependencies = [ + "adler2", +] + +[[package]] +name = "mio" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "object" +version = "0.36.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62948e14d923ea95ea2c7c86c71013138b66525b86bdc08d2dcc262bdb497b87" +dependencies = [ + "memchr", +] + +[[package]] +name = "parking_lot" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-targets", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + [[package]] name = "proc-macro2" version = "1.0.93" @@ -36,6 +307,15 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redox_syscall" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03a862b389f93e68874fbf580b9de08dd02facb9a788ebadaf4a3fd33cf58834" +dependencies = [ + "bitflags", +] + [[package]] name = "ref-cast" version = "1.0.23" @@ -56,18 +336,54 @@ dependencies = [ "syn", ] +[[package]] +name = "rustc-demangle" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "signal-hook-registry" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +dependencies = [ + "libc", +] + +[[package]] +name = "smallvec" +version = "1.13.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" + +[[package]] +name = "socket2" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "soda" version = "0.1.0" dependencies = [ "fluent-uri", - "soda_macros", + "http-body-util", + "hyper", + "hyper-util", + "tokio", ] -[[package]] -name = "soda_macros" -version = "0.1.0" - [[package]] name = "syn" version = "2.0.98" @@ -79,8 +395,116 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tokio" +version = "1.43.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3d61fa4ffa3de412bfea335c6ecff681de2b609ba3c77ef3e00e521813a9ed9e" +dependencies = [ + "backtrace", + "bytes", + "libc", + "mio", + "parking_lot", + "pin-project-lite", + "signal-hook-registry", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-macros" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e06d43f1345a3bcd39f6a56dbb7dcab2ba47e68e8ac134855e7e2bdbaf8cab8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "unicode-ident" version = "1.0.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a210d160f08b701c8721ba1c726c11662f877ea6b7094007e1ca9a1041945034" + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" diff --git a/Cargo.toml b/Cargo.toml index f969df0..e1e0616 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,4 +4,8 @@ version = "0.1.0" edition = "2021" [dependencies] -fluent-uri = "0.3.2" \ No newline at end of file +fluent-uri = "0.3.2" +hyper = { version = "1.6", features = ["server", "http1"] } +tokio = { version = "1", features = ["full"] } +http-body-util = "*" +hyper-util = { version = "*", features = ["tokio"] } \ No newline at end of file diff --git a/examples/hello.rs b/examples/hello.rs index 052f9d4..4c621ee 100644 --- a/examples/hello.rs +++ b/examples/hello.rs @@ -6,9 +6,15 @@ use soda::prelude::*; #[tokio::main] -fn main() { - let app = PageBase("Test Page", - Tag::Heading1("hi!") +async fn main() { + let page = PageBase("Test Page", + ( + Tag::Heading1("Hello, World!"), + Tag::Paragraph("This is a test of Soda, an ultrafast composable frontend framework built in Rust!") + ) ); - Server::new((0.0.0.0, 3000)).unwrap().serve(app).await; + let app = page.route(); + Server::new(([0, 0, 0, 0], 3000)).await.unwrap().serve(app, ()).await.unwrap(); + // weird rustc bug: if the second argument is omitted, rustc gets stuck in a recursion trying to figure out what type State is + // *before* exiting on the error produced by the missing argument. this consumes cpu and slowly eats ram until it OOMs or you kill it. } \ No newline at end of file diff --git a/generate-composer-impls.py b/generate-composer-impls.py index 3d6ad8f..bbde79a 100644 --- a/generate-composer-impls.py +++ b/generate-composer-impls.py @@ -12,7 +12,7 @@ print("use crate::compose::Compose;") print("use crate::output::Output;") for x in range(1, 32): - nprint("impl" for n in range(0, x)])) nprint("> Compose for (") nprint("".join([tp(n) + "," for n in range(0, x)])) diff --git a/src/compose.rs b/src/compose.rs index 12586ac..6c3acfb 100644 --- a/src/compose.rs +++ b/src/compose.rs @@ -4,37 +4,41 @@ use crate::output::Output; use crate::router::{ self, RouteTerminate, Router }; -pub trait Compose { +pub trait Compose : Send + Sync { fn render(&self, output : &mut impl Output, state : &mut State); - fn route(self, r : &'static str) -> impl Router where Self : Sized { - router::route(r).then(RouteTerminate::build(self)) + fn route_at(self, r : &'static str) -> impl Router where Self : Sized { + router::route(r).then(self.route()) + } + + fn route(self) -> impl Router where Self : Sized { + RouteTerminate::build(self) } } -impl Compose for () { +impl Compose for () { fn render(&self, _output : &mut impl Output, _state : &mut State) { } } -impl Compose for &'static str { +impl Compose for &'static str { fn render(&self, output : &mut impl Output, _state : &mut State) { output.write(self); } } -impl Compose for String { +impl Compose for String { fn render(&self, output : &mut impl Output, _state : &mut State) { output.write(self.as_str()); } } -impl, T : Fn(&mut St) -> S> Compose for T { +impl, T : Fn(&mut St) -> S + Send + Sync> Compose for T { fn render(&self, output : &mut impl Output, state : &mut St) { self(state).render(output, state); } diff --git a/src/html.rs b/src/html.rs index d372b6f..c5bf97e 100644 --- a/src/html.rs +++ b/src/html.rs @@ -3,7 +3,7 @@ use crate::output::Output; use std::marker::PhantomData; -pub trait HTMLTag : Compose { +pub trait HTMLTag : Compose { fn get_tagname(&self) -> &'static str; fn does_self_close(&self) -> bool; @@ -40,7 +40,7 @@ pub trait HTMLTag : Compose { } -pub struct WithProperty + Sized> { +pub struct WithProperty + Sized> { name : &'static str, value : &'static str, lower_tag : T, @@ -48,7 +48,7 @@ pub struct WithProperty + Sized> { } -impl> HTMLTag for WithProperty { +impl> HTMLTag for WithProperty { fn get_tagname(&self) -> &'static str { self.lower_tag.get_tagname() } @@ -72,21 +72,21 @@ impl> HTMLTag for WithProperty { } -impl + Sized, State> Compose for WithProperty { +impl + Sized, State : Send + Sync> Compose for WithProperty { fn render(&self, out : &mut impl Output, state : &mut State) { self.helpful_provided_render_function(out, state); } } -impl, State> Compose for StandardTags { +impl, State : Send + Sync> Compose for StandardTags { fn render(&self, out : &mut impl Output, state : &mut State) { self.helpful_provided_render_function(out, state); } } -impl Compose for SelfClosingTags { +impl Compose for SelfClosingTags { fn render(&self, out : &mut impl Output, state : &mut State) { self.helpful_provided_render_function(out, state); } @@ -109,7 +109,7 @@ pub enum SelfClosingTags { } -impl HTMLTag for SelfClosingTags { +impl HTMLTag for SelfClosingTags { fn get_tagname(&self) -> &'static str { match self { Self::Meta => "meta" @@ -136,7 +136,7 @@ impl StandardTags { } } -impl> HTMLTag for StandardTags { +impl> HTMLTag for StandardTags { fn get_tagname(&self) -> &'static str { match self { Self::Html(_) => "html", @@ -173,7 +173,7 @@ pub fn Doctype() -> &'static str { #[allow(non_snake_case)] -pub fn PageBase(title : &'static str, body : impl Compose) -> impl Compose { +pub fn PageBase(title : &'static str, body : impl Compose) -> impl Compose { ( Doctype(), Tag::Html(( diff --git a/src/lib.rs b/src/lib.rs index a30bf46..98ed579 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,9 +49,9 @@ mod tests { let page1 = template("this is the first page"); let page2 = template("this is the second page"); let page3 = template("this is the third page"); - let app = page1.route("page1") // route GET /page1 - .or(page2.route("page2")) // route GET /page2 - .or(router::route("page_num").then(page3.route("3"))); // route GET /page_num/3 + let app = page1.route_at("page1") // route GET /page1 + .or(page2.route_at("page2")) // route GET /page2 + .or(router::route("page_num").then(page3.route_at("3"))); // route GET /page_num/3 let mut output = output::DummyOutput::new(); app.get("https://web.app/page1").unwrap().render(&mut output, &mut ()); assert_eq!(output.spool(), r#"My Webpage

My Test Website

this is the first page
"#); diff --git a/src/output.rs b/src/output.rs index 56dff8d..72f20bd 100644 --- a/src/output.rs +++ b/src/output.rs @@ -30,4 +30,25 @@ impl DummyOutput { out : String::new() } } +} + + +pub struct StringFillerOutput<'s> { + string : &'s mut String +} + + +impl<'s> Output for StringFillerOutput<'s> { + fn write(&mut self, data : &str) { + *self.string += data; + } +} + +impl<'a> StringFillerOutput<'a> { + pub fn new(string : &'a mut String) -> StringFillerOutput<'a> { + // TODO: reserve() to make this faster than dummyoutput + StringFillerOutput { + string + } + } } \ No newline at end of file diff --git a/src/router.rs b/src/router.rs index 6f8a99f..9360d90 100644 --- a/src/router.rs +++ b/src/router.rs @@ -4,7 +4,7 @@ use fluent_uri::{ Uri }; use std::marker::PhantomData; -pub trait Router> { // routers match paths and return a +pub trait Router + Send + Sync> : Send + Sync { // routers match paths and return a fn or>(self, other : T) -> OrRouter where Self : Sized { // route EITHER this router or another router, tries this router first OrRouter { one : self, @@ -43,7 +43,7 @@ pub struct PathRouter { } -impl Router for PathRouter { +impl Router for PathRouter { fn unitize(self) -> impl Router { self } @@ -59,14 +59,14 @@ impl Router for PathRouter { } -pub struct ThenRouter, FirstRouter : Router, SecondRouter : Router> { +pub struct ThenRouter, FirstRouter : Router, SecondRouter : Router> { one : FirstRouter, two : SecondRouter, _phantom : PhantomData<(Out, State)> } -impl, FirstRouter : Router, SecondRouter : Router> Router for ThenRouter { +impl, FirstRouter : Router, SecondRouter : Router> Router for ThenRouter { fn unitize(self) -> impl Router { ThenRouter { one : self.one, @@ -86,14 +86,14 @@ impl, FirstRouter : Router, SecondRouter } -pub struct OrRouter, FirstRouter : Router, SecondRouter : Router> { +pub struct OrRouter, FirstRouter : Router, SecondRouter : Router> { one : FirstRouter, two : SecondRouter, _phantom : PhantomData<(State, Out)> } -impl, FirstRouter : Router, SecondRouter : Router> Router for OrRouter { +impl, FirstRouter : Router, SecondRouter : Router> Router for OrRouter { fn unitize(self) -> impl Router { OrRouter { one : self.one.unitize(), @@ -120,13 +120,13 @@ impl, FirstRouter : Router, SecondRouter } -pub struct RouteTerminate> { // terminate a route in a composer. cannot fail; this is not a filter. +pub struct RouteTerminate> { // terminate a route in a composer. cannot fail; this is not a filter. output : Out, _phantom : PhantomData } -impl + Sized> RouteTerminate { +impl + Sized> RouteTerminate { pub fn build(thing : Out) -> RouteTerminate { RouteTerminate { output : thing, @@ -136,7 +136,7 @@ impl + Sized> RouteTerminate { } -impl + Sized> Router for RouteTerminate { +impl + Sized> Router for RouteTerminate { fn unitize(self) -> impl Router { RouteTerminate:: { output : (), @@ -144,7 +144,13 @@ impl + Sized> Router for RouteTerminate } } - fn route<'a, T : AsRef>(&'a self, _path : &mut (impl Iterator + Clone)) -> Option<&'a Out> { + fn route<'a, T : AsRef>(&'a self, path : &mut (impl Iterator + Clone)) -> Option<&'a Out> { + if let Some(next) = path.next() { + let next : &str = next.as_ref(); + if next.len() > 0 { + return None; + } + } Some(&self.output) } } diff --git a/src/server.rs b/src/server.rs index 58be68d..cfa535e 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,46 +1,74 @@ // webserver that forwards requests to Routes // based on Hyper -use std::convert::Infallible; use std::net::SocketAddr; use http_body_util::Full; use hyper::body::Bytes; use hyper::server::conn::http1; use hyper::service::service_fn; -use hyper::{Request, Response}; +use hyper::Response; use hyper_util::rt::TokioIo; use tokio::net::TcpListener; use std::sync::{ Arc, Mutex }; -use crate::router::Router; +use std::ops::DerefMut; + +use crate::prelude::*; -struct Server { - addr : SocketAddr, +pub struct Server { listener : TcpListener } +fn not_found() -> Response>{ + Response::builder().status(hyper::StatusCode::NOT_FOUND).body(Full::new(Bytes::from("Not Found"))).unwrap() // TODO: no unwrap +} + + +fn internal_server_error() -> Response>{ + Response::builder().status(hyper::StatusCode::INTERNAL_SERVER_ERROR).body(Full::new(Bytes::from("Internal Server Error"))).unwrap() // TODO: no unwrap +} + + impl Server { - pub fn new(addr : ([u8; 4], u16)) -> Result> { + pub async fn new(addr : ([u8; 4], u16)) -> Result> { let addr = SocketAddr::from(addr); Ok(Server { - addr, listener : TcpListener::bind(addr).await? }) } - pub async fn serve(&self, rt : impl Router, state : T) -> Result<(), Box> { + pub async fn serve>(&self, rt : impl Router + Send + Sync + 'static, state : T) -> Result<(), Box> { let state = Arc::new(Mutex::new(state)); + let router = Arc::new(rt); loop { let (stream, _) = self.listener.accept().await?; let io = TokioIo::new(stream); let state = state.clone(); + let router = router.clone(); let service = service_fn(move |req| { + let state = state.clone(); + let router = router.clone(); async move { - + let mut path = req.uri().path().split("/"); + path.next(); + let mut render_result = String::new(); // TODO: make this more efficient + let mut out = output::StringFillerOutput::new(&mut render_result); + if let Some(page) = router.route(&mut path) { + if let Ok(mut lock) = state.lock() { + page.render(&mut out, lock.deref_mut()); + } + else { + return Ok(internal_server_error()); + } + } + else { + return Ok(not_found()); + } + Ok::<_, hyper::Error>(Response::new(Full::new(Bytes::from(render_result)))) } }); tokio::task::spawn(async move { diff --git a/src/tuples.rs b/src/tuples.rs index 0a2075d..340b0a9 100644 --- a/src/tuples.rs +++ b/src/tuples.rs @@ -1,24 +1,24 @@ use crate::compose::Compose; use crate::output::Output; -impl> Compose for (T1,) { +impl> Compose for (T1,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); } } -impl, T2 : Compose> Compose for (T1,T2,) { +impl, T2 : Compose> Compose for (T1,T2,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); } } -impl, T2 : Compose, T3 : Compose> Compose for (T1,T2,T3,) { +impl, T2 : Compose, T3 : Compose> Compose for (T1,T2,T3,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); self.2.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose> Compose for (T1,T2,T3,T4,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose> Compose for (T1,T2,T3,T4,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -26,7 +26,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.3.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose> Compose for (T1,T2,T3,T4,T5,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose> Compose for (T1,T2,T3,T4,T5,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -35,7 +35,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.4.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose> Compose for (T1,T2,T3,T4,T5,T6,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose> Compose for (T1,T2,T3,T4,T5,T6,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -45,7 +45,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.5.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -56,7 +56,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.6.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -68,7 +68,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.7.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -81,7 +81,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.8.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -95,7 +95,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.9.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -110,7 +110,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.10.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -126,7 +126,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.11.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -143,7 +143,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.12.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -161,7 +161,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.13.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -180,7 +180,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.14.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -200,7 +200,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.15.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -221,7 +221,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.16.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -243,7 +243,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.17.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -266,7 +266,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.18.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -290,7 +290,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.19.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -315,7 +315,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.20.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -341,7 +341,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.21.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -368,7 +368,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.22.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -396,7 +396,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.23.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -425,7 +425,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.24.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -455,7 +455,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.25.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -486,7 +486,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.26.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose, T28 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose, T28 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -518,7 +518,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.27.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose, T28 : Compose, T29 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose, T28 : Compose, T29 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -551,7 +551,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.28.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose, T28 : Compose, T29 : Compose, T30 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose, T28 : Compose, T29 : Compose, T30 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state); @@ -585,7 +585,7 @@ impl, T2 : Compose, T3 : Compose, T4 : C self.29.render(output, state); } } -impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose, T28 : Compose, T29 : Compose, T30 : Compose, T31 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,) { +impl, T2 : Compose, T3 : Compose, T4 : Compose, T5 : Compose, T6 : Compose, T7 : Compose, T8 : Compose, T9 : Compose, T10 : Compose, T11 : Compose, T12 : Compose, T13 : Compose, T14 : Compose, T15 : Compose, T16 : Compose, T17 : Compose, T18 : Compose, T19 : Compose, T20 : Compose, T21 : Compose, T22 : Compose, T23 : Compose, T24 : Compose, T25 : Compose, T26 : Compose, T27 : Compose, T28 : Compose, T29 : Compose, T30 : Compose, T31 : Compose> Compose for (T1,T2,T3,T4,T5,T6,T7,T8,T9,T10,T11,T12,T13,T14,T15,T16,T17,T18,T19,T20,T21,T22,T23,T24,T25,T26,T27,T28,T29,T30,T31,) { fn render(&self, output : &mut impl Output, state : &mut State) { self.0.render(output, state); self.1.render(output, state);