chiark / gitweb /
multipart: process_boundary: Rename, and better docs
[hippotat.git] / src / multipart.rs
index 5099f05fe120b24fb9974060e599dd631f7774bc..b076458100315b3cf37469a0086b763043def6bd 100644 (file)
@@ -7,7 +7,7 @@ use crate::prelude::*;
 #[derive(Debug)]
 pub struct Component<'b> {
   pub name: PartName,
-  pub payload_start: &'b [u8],
+  pub payload: &'b [u8],
 }
 
 #[derive(Debug)]
@@ -15,10 +15,16 @@ pub struct Component<'b> {
 #[allow(non_camel_case_types)]
 pub enum PartName { m, d, Other }
 
+pub type BoundaryFinder = memchr::memmem::Finder<'static>;
+
 #[throws(AE)]
-pub fn process_component<'b>(warnings: &mut Warnings,
-                             after_leader: &'b [u8], expected: PartName)
-                             -> Option<Component<'b>> {
+/// Processes the start of a component (or terminating boundary).
+///
+/// Returned payload is only the start of the payload; the next
+/// boundary has not been identified.
+pub fn process_boundary<'b>(warnings: &mut Warnings,
+                            after_leader: &'b [u8], expected: PartName)
+                            -> Option<Component<'b>> {
   let rhs = after_leader;
   let mut rhs =
        if let Some(rhs) = rhs.strip_prefix(b"\r\n") { rhs         }
@@ -71,7 +77,7 @@ pub fn process_component<'b>(warnings: &mut Warnings,
     };
   }
 
-  Some(Component { name: part_name.unwrap_or(expected), payload_start: rhs })
+  Some(Component { name: part_name.unwrap_or(expected), payload: rhs })
 }
 
 pub struct MetadataFieldIterator<'b> {
@@ -88,9 +94,15 @@ impl<'b> MetadataFieldIterator<'b> {
   } }
 
   #[throws(AE)]
-  pub fn need<T>(&mut self) -> T
+  pub fn need_next(&mut self) -> &'b str
+  {
+    self.next().ok_or_else(|| anyhow!("missing"))??
+  }
+
+  #[throws(AE)]
+  pub fn need_parse<T>(&mut self) -> T
   where T: FromStr,
-        T::Err: std::error::Error + Sync + Send + 'static,
+        AE: From<T::Err>,
   {
     self.parse()?.ok_or_else(|| anyhow!("missing"))?
   }
@@ -98,11 +110,19 @@ impl<'b> MetadataFieldIterator<'b> {
   #[throws(AE)]
   pub fn parse<T>(&mut self) -> Option<T>
   where T: FromStr,
-        T::Err: std::error::Error + Sync + Send + 'static,
+        AE: From<T::Err>,
   {
     let s = if let Some(r) = self.next() { r? } else { return None };
     Some(s.parse()?)
   }
+
+  pub fn remaining_bytes_len(&self) -> usize {
+    if let Some(last) = self.last {
+      self.buf.len() - last
+    } else {
+      0
+    }
+  }
 }
                                       
 impl<'b> Iterator for MetadataFieldIterator<'b> {