chiark / gitweb /
server: MetadataFieldIterator
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 8 Aug 2021 19:45:12 +0000 (20:45 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 8 Aug 2021 19:45:12 +0000 (20:45 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
src/bin/server.rs
src/multipart.rs
src/prelude.rs

index 1c8a64cd49622ec38f72880122125fb045cbd7bb..c5eaf9296a99be682fff4d3b7b86e1a0ece0b59c 100644 (file)
@@ -88,11 +88,13 @@ async fn handle(
       r#"first multipart component must be name="m""#
     )) }
 
-    let nl = memchr::memchr2(b'\r', b'\n', comp.payload_start)
-      .ok_or_else(|| anyhow!("no newline in first metadata line?"))?;
+    let mut meta = MetadataFieldIterator::new(comp.payload_start);
+
+    let client = meta.next()
+      .map(|r| r.map_err(Into::into))
+      .unwrap_or_else(|| Err(anyhow!("missing")))
+      .context("client addr")?;
 
-    let client = &comp.payload_start[0..nl];
-    let client = str::from_utf8(client).context("client addr utf-8")?;
     let client: IpAddr = client.parse().context("client address")?;
 // let client = all_clients.get(&client).ok_or_else(|| anyhow!(BAD_CLIENT))?;
 
index e01b0f30eb24a5878c6655349d48361d0f0333cd..112712bb8d5f4ad79d78f5e66473039b4357f46f 100644 (file)
@@ -73,3 +73,31 @@ pub fn process_component<'b>(warnings: &mut Warnings,
 
   Some(Component { name: part_name.unwrap_or(expected), payload_start: rhs })
 }
+
+pub struct MetadataFieldIterator<'b> {
+  buf: &'b [u8],
+  last: Option<usize>,
+  iter: memchr::Memchr<'b>,
+}
+
+impl<'b> MetadataFieldIterator<'b> {
+  pub fn new(buf: &'b [u8]) -> Self { Self {
+    buf,
+    last: Some(0),
+    iter: memchr::Memchr::new(b'\n', buf),
+  } }
+}
+                                      
+impl<'b> Iterator for MetadataFieldIterator<'b> {
+  type Item = Result<&'b str, std::str::Utf8Error>;
+  fn next(&mut self) -> Option<Result<&'b str, std::str::Utf8Error>> {
+    let last = self.last?;
+    let (s, last) = match self.iter.next() {
+      Some(nl) => (&self.buf[last..nl], Some(nl+1)),
+      None     => (&self.buf[last..],   None),
+    };
+    self.last = last;
+    let s = str::from_utf8(s).map(|s| s.trim());
+    Some(s)
+  }
+}
index 22a9c27550b81b9623bc261a34980059f46998fa..931a9fa15d3155144a84e7d7d91e587f3203cd30 100644 (file)
@@ -56,7 +56,7 @@ pub use eyre::Error as AE;
 pub use crate::config::{self, InstanceConfig, u32Ext as _};
 pub use crate::ini;
 pub use crate::ipif::Ipif;
-pub use crate::multipart::{self, PartName};
+pub use crate::multipart::{self, PartName, MetadataFieldIterator};
 pub use crate::utils::*;
 pub use crate::queue::*;
 pub use crate::reporter::*;