Add a `HttpRepositoryBuilder` and move min_bytes_per_second

The `HttpRepository::new` method takes a lot of options that I
expect people will just set the default. This makes it easier
to ignore unset options.

Also, the `min_bytes_per_second` seems more like a setting that
we'd want set globally, rather than on a per-repository-method call.
Since this setting really only makes sense on `HttpRepository`,
I've also moved this setting into the builder.
diff --git a/src/client.rs b/src/client.rs
index 4815084..f306552 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -13,7 +13,7 @@
 //! # use tuf::metadata::{RootMetadata, SignedMetadata, Role, MetadataPath,
 //! #     MetadataVersion};
 //! # use tuf::interchange::Json;
-//! # use tuf::repository::{Repository, FileSystemRepository, HttpRepository};
+//! # use tuf::repository::{Repository, FileSystemRepository, HttpRepositoryBuilder};
 //!
 //! static TRUSTED_ROOT_KEY_IDS: &'static [&str] = &[
 //!     "diNfThTFm0PI8R-Bq7NztUIvZbZiaC_weJBgcqaHlWw=",
@@ -29,11 +29,12 @@
 //!
 //! let local = FileSystemRepository::<Json>::new(PathBuf::from("~/.rustup"))?;
 //!
-//! let remote = HttpRepository::new(
+//! let remote = HttpRepositoryBuilder::new(
 //!     url::Url::parse("https://static.rust-lang.org/").unwrap(),
 //!     HttpClient::new(),
-//!     Some("rustup/1.4.0".into()),
-//!     None);
+//! )
+//! .user_agent_prefix("rustup/1.4.0")
+//! .build();
 //!
 //! let mut client = await!(Client::with_root_pinned(
 //!     &key_ids,
@@ -142,7 +143,6 @@
             &root_path,
             &root_version,
             &config.max_root_size,
-            config.min_bytes_per_second,
             None,
         ))?;
 
@@ -173,7 +173,6 @@
             &root_path,
             &root_version,
             &config.max_root_size,
-            config.min_bytes_per_second,
             None,
         )) {
             Ok(root) => root,
@@ -183,7 +182,6 @@
                     &root_path,
                     &root_version,
                     &config.max_root_size,
-                    config.min_bytes_per_second,
                     None,
                 ))?;
 
@@ -249,7 +247,6 @@
             &root_path,
             &MetadataVersion::None,
             &self.config.max_root_size,
-            self.config.min_bytes_per_second,
             None,
         ))?;
         let latest_version = latest_root.version();
@@ -274,7 +271,6 @@
                 &root_path,
                 &version,
                 &self.config.max_root_size,
-                self.config.min_bytes_per_second,
                 None,
             ))?;
 
@@ -312,7 +308,6 @@
             &timestamp_path,
             &MetadataVersion::None,
             &self.config.max_timestamp_size,
-            self.config.min_bytes_per_second,
             None,
         ))?;
 
@@ -358,7 +353,6 @@
             &snapshot_path,
             &version,
             &snapshot_size,
-            self.config.min_bytes_per_second,
             Some((alg, value.clone())),
         ))?;
 
@@ -405,7 +399,6 @@
             &targets_path,
             &version,
             &targets_size,
-            self.config.min_bytes_per_second,
             Some((alg, value.clone())),
         ))?;
 
@@ -451,7 +444,6 @@
         await!(self.remote.fetch_target(
             target,
             &target_description,
-            self.config.min_bytes_per_second,
         ))
     }
 
@@ -526,7 +518,6 @@
                 delegation.role(),
                 &MetadataVersion::None,
                 &role_size,
-                self.config.min_bytes_per_second(),
                 Some((alg, value.clone())),
             ));
 
@@ -537,7 +528,6 @@
                         delegation.role(),
                         &version,
                         &role_size,
-                        self.config.min_bytes_per_second(),
                         Some((alg, value.clone())),
                     )) {
                         Ok(m) => m,
@@ -613,7 +603,6 @@
 /// let config = Config::default();
 /// assert_eq!(config.max_root_size(), &Some(1024 * 1024));
 /// assert_eq!(config.max_timestamp_size(), &Some(32 * 1024));
-/// assert_eq!(config.min_bytes_per_second(), 4096);
 /// assert_eq!(config.max_delegation_depth(), 8);
 /// let _: &DefaultTranslator = config.path_translator();
 /// ```
@@ -624,7 +613,6 @@
 {
     max_root_size: Option<usize>,
     max_timestamp_size: Option<usize>,
-    min_bytes_per_second: u32,
     max_delegation_depth: u32,
     path_translator: T,
 }
@@ -650,11 +638,6 @@
         &self.max_timestamp_size
     }
 
-    /// The minimum bytes per second for a read to be considered good.
-    pub fn min_bytes_per_second(&self) -> u32 {
-        self.min_bytes_per_second
-    }
-
     /// The maximum number of steps used when walking the delegation graph.
     pub fn max_delegation_depth(&self) -> u32 {
         self.max_delegation_depth
@@ -671,7 +654,6 @@
         Config {
             max_root_size: Some(1024 * 1024),
             max_timestamp_size: Some(32 * 1024),
-            min_bytes_per_second: 4096,
             max_delegation_depth: 8,
             path_translator: DefaultTranslator::new(),
         }
@@ -686,7 +668,6 @@
 {
     max_root_size: Option<usize>,
     max_timestamp_size: Option<usize>,
-    min_bytes_per_second: u32,
     max_delegation_depth: u32,
     path_translator: T,
 }
@@ -700,7 +681,6 @@
         Ok(Config {
             max_root_size: self.max_root_size,
             max_timestamp_size: self.max_timestamp_size,
-            min_bytes_per_second: self.min_bytes_per_second,
             max_delegation_depth: self.max_delegation_depth,
             path_translator: self.path_translator,
         })
@@ -718,12 +698,6 @@
         self
     }
 
-    /// Set the minimum bytes per second for a read to be considered good.
-    pub fn min_bytes_per_second(mut self, min: u32) -> Self {
-        self.min_bytes_per_second = min;
-        self
-    }
-
     /// Set the maximum number of steps used when walking the delegation graph.
     pub fn max_delegation_depth(mut self, max: u32) -> Self {
         self.max_delegation_depth = max;
@@ -738,7 +712,6 @@
         ConfigBuilder {
             max_root_size: self.max_root_size,
             max_timestamp_size: self.max_timestamp_size,
-            min_bytes_per_second: self.min_bytes_per_second,
             max_delegation_depth: self.max_delegation_depth,
             path_translator,
         }
@@ -751,7 +724,6 @@
         ConfigBuilder {
             max_root_size: cfg.max_root_size,
             max_timestamp_size: cfg.max_timestamp_size,
-            min_bytes_per_second: cfg.min_bytes_per_second,
             max_delegation_depth: cfg.max_delegation_depth,
             path_translator: cfg.path_translator,
         }
@@ -771,7 +743,6 @@
     use chrono::prelude::*;
     use futures::executor::block_on;
     use lazy_static::lazy_static;
-    use std::u32;
 
     lazy_static! {
         static ref KEYS: Vec<PrivateKey> = {
@@ -937,7 +908,6 @@
                 &MetadataPath::from_role(&Role::Root),
                 &MetadataVersion::Number(1),
                 &None,
-                u32::MAX,
                 None
             ))
             .unwrap(),
@@ -986,7 +956,6 @@
                 &MetadataPath::from_role(&Role::Root),
                 &MetadataVersion::Number(3),
                 &None,
-                u32::MAX,
                 None
             ))
             .unwrap(),
diff --git a/src/repository.rs b/src/repository.rs
index 4f798ca..50f1923 100644
--- a/src/repository.rs
+++ b/src/repository.rs
@@ -53,7 +53,6 @@
         meta_path: &'a MetadataPath,
         version: &'a MetadataVersion,
         max_size: &'a Option<usize>,
-        min_bytes_per_second: u32,
         hash_data: Option<(&'static HashAlgorithm, HashValue)>,
     ) -> TufFuture<'a, Result<SignedMetadata<D, M>>>
     where
@@ -73,7 +72,6 @@
         &'a self,
         target_path: &'a TargetPath,
         target_description: &'a TargetDescription,
-        min_bytes_per_second: u32,
     ) -> TufFuture<'a, Result<Box<dyn AsyncRead>>>;
 
     /// Perform a sanity check that `M`, `Role`, and `MetadataPath` all desrcribe the same entity.
@@ -160,7 +158,6 @@
         meta_path: &'a MetadataPath,
         version: &'a MetadataVersion,
         max_size: &'a Option<usize>,
-        min_bytes_per_second: u32,
         hash_data: Option<(&'static HashAlgorithm, HashValue)>,
     ) -> TufFuture<'a, Result<SignedMetadata<D, M>>>
     where
@@ -176,7 +173,7 @@
                 let mut reader = SafeReader::new(
                     AllowStdIo::new(File::open(&path)?),
                     max_size.unwrap_or(::std::usize::MAX) as u64,
-                    min_bytes_per_second,
+                    0,
                     hash_data,
                 )?;
 
@@ -218,7 +215,6 @@
         &'a self,
         target_path: &'a TargetPath,
         target_description: &'a TargetDescription,
-        min_bytes_per_second: u32,
     ) -> TufFuture<'a, Result<Box<dyn AsyncRead>>> {
         Box::pinned(
             async move {
@@ -234,7 +230,7 @@
                 let reader: Box<dyn AsyncRead> = Box::new(SafeReader::new(
                     AllowStdIo::new(File::open(&path)?),
                     target_description.size(),
-                    min_bytes_per_second,
+                    0,
                     Some((alg, value.clone())),
                 )?);
 
@@ -258,16 +254,92 @@
     }
 }
 
+/// A builder to create a repository accessible over HTTP.
+pub struct HttpRepositoryBuilder<C, D>
+where
+    C: Connect + Sync + 'static,
+    D: DataInterchange,
+{
+    url: Url,
+    client: Client<C>,
+    interchange: PhantomData<D>,
+    user_agent_prefix: Option<String>,
+    metadata_prefix: Option<Vec<String>>,
+    min_bytes_per_second: u32,
+}
+
+impl<C, D> HttpRepositoryBuilder<C, D>
+where
+    C: Connect + Sync + 'static,
+    D: DataInterchange,
+{
+    /// Create a new repository with the given `Url` and `Client`.
+    pub fn new(url: Url, client: Client<C>) -> Self {
+        HttpRepositoryBuilder {
+            url: url,
+            client: client,
+            interchange: PhantomData,
+            user_agent_prefix: None,
+            metadata_prefix: None,
+            min_bytes_per_second: 4096,
+        }
+    }
+
+    /// Set the User-Agent prefix.
+    ///
+    /// Callers *should* include a custom User-Agent prefix to help maintainers of TUF repositories
+    /// keep track of which client versions exist in the field.
+    ///
+    pub fn user_agent_prefix<T: Into<String>>(mut self, user_agent_prefix: T) -> Self {
+        self.user_agent_prefix = Some(user_agent_prefix.into());
+        self
+    }
+
+    /// The argument `metadata_prefix` is used provide an alternate path where metadata is stored on
+    /// the repository. If `None`, this defaults to `/`. For example, if there is a TUF repository
+    /// at `https://tuf.example.com/`, but all metadata is stored at `/meta/`, then passing the
+    /// arg `Some("meta".into())` would cause `root.json` to be fetched from
+    /// `https://tuf.example.com/meta/root.json`.
+    pub fn metadata_prefix(mut self, metadata_prefix: Vec<String>) -> Self {
+        self.metadata_prefix = Some(metadata_prefix);
+        self
+    }
+
+    /// Set the minimum bytes per second for a read to be considered good.
+    pub fn min_bytes_per_second(mut self, min: u32) -> Self {
+        self.min_bytes_per_second = min;
+        self
+    }
+
+    /// Build a `HttpRepository`.
+    pub fn build(self) -> HttpRepository<C, D> {
+        let user_agent = match self.user_agent_prefix {
+            Some(ua) => format!("{} (rust-tuf/{})", ua, env!("CARGO_PKG_VERSION")),
+            None => format!("rust-tuf/{}", env!("CARGO_PKG_VERSION")),
+        };
+
+        HttpRepository {
+            url: self.url,
+            client: self.client,
+            interchange: self.interchange,
+            user_agent: user_agent,
+            metadata_prefix: self.metadata_prefix,
+            min_bytes_per_second: self.min_bytes_per_second,
+        }
+    }
+}
+
 /// A repository accessible over HTTP.
 pub struct HttpRepository<C, D>
 where
-    C: Connect + Sync,
+    C: Connect + Sync + 'static,
     D: DataInterchange,
 {
     url: Url,
     client: Client<C>,
     user_agent: String,
     metadata_prefix: Option<Vec<String>>,
+    min_bytes_per_second: u32,
     interchange: PhantomData<D>,
 }
 
@@ -276,36 +348,6 @@
     C: Connect + Sync + 'static,
     D: DataInterchange,
 {
-    /// Create a new repository with the given `Url` and `Client`.
-    ///
-    /// Callers *should* include a custom User-Agent prefix to help maintainers of TUF repositories
-    /// keep track of which client versions exist in the field.
-    ///
-    /// The argument `metadata_prefix` is used provide an alternate path where metadata is stored on
-    /// the repository. If `None`, this defaults to `/`. For example, if there is a TUF repository
-    /// at `https://tuf.example.com/`, but all metadata is stored at `/meta/`, then passing the
-    /// arg `Some("meta".into())` would cause `root.json` to be fetched from
-    /// `https://tuf.example.com/meta/root.json`.
-    pub fn new(
-        url: Url,
-        client: Client<C>,
-        user_agent_prefix: Option<String>,
-        metadata_prefix: Option<Vec<String>>,
-    ) -> Self {
-        let user_agent = match user_agent_prefix {
-            Some(ua) => format!("{} (rust-tuf/{})", ua, env!("CARGO_PKG_VERSION")),
-            None => format!("rust-tuf/{}", env!("CARGO_PKG_VERSION")),
-        };
-
-        HttpRepository {
-            url,
-            client,
-            user_agent,
-            metadata_prefix,
-            interchange: PhantomData,
-        }
-    }
-
     async fn get<'a>(
         &'a self,
         prefix: &'a Option<Vec<String>>,
@@ -378,7 +420,6 @@
         meta_path: &'a MetadataPath,
         version: &'a MetadataVersion,
         max_size: &'a Option<usize>,
-        min_bytes_per_second: u32,
         hash_data: Option<(&'static HashAlgorithm, HashValue)>,
     ) -> TufFuture<'a, Result<SignedMetadata<D, M>>>
     where
@@ -399,7 +440,7 @@
                 let mut reader = SafeReader::new(
                     IntoAsyncRead::new(stream),
                     max_size.unwrap_or(::std::usize::MAX) as u64,
-                    min_bytes_per_second,
+                    self.min_bytes_per_second,
                     hash_data,
                 )?;
 
@@ -423,7 +464,6 @@
         &'a self,
         target_path: &'a TargetPath,
         target_description: &'a TargetDescription,
-        min_bytes_per_second: u32,
     ) -> TufFuture<'a, Result<Box<dyn AsyncRead>>> {
         Box::pinned(
             async move {
@@ -439,7 +479,7 @@
                 let reader = SafeReader::new(
                     IntoAsyncRead::new(stream),
                     target_description.size(),
-                    min_bytes_per_second,
+                    self.min_bytes_per_second,
                     Some((alg, value.clone())),
                 )?;
 
@@ -514,7 +554,6 @@
         meta_path: &'a MetadataPath,
         version: &'a MetadataVersion,
         max_size: &'a Option<usize>,
-        min_bytes_per_second: u32,
         hash_data: Option<(&'static HashAlgorithm, HashValue)>,
     ) -> TufFuture<'a, Result<SignedMetadata<D, M>>>
     where
@@ -530,7 +569,7 @@
                         let mut reader = SafeReader::new(
                             &**bytes,
                             max_size.unwrap_or(::std::usize::MAX) as u64,
-                            min_bytes_per_second,
+                            0,
                             hash_data,
                         )?;
 
@@ -569,7 +608,6 @@
         &'a self,
         target_path: &'a TargetPath,
         target_description: &'a TargetDescription,
-        min_bytes_per_second: u32,
     ) -> TufFuture<'a, Result<Box<dyn AsyncRead>>> {
         Box::pinned(
             async move {
@@ -582,7 +620,7 @@
                         let reader: Box<dyn AsyncRead> = Box::new(SafeReader::new(
                             cur,
                             target_description.size(),
-                            min_bytes_per_second,
+                            0,
                             Some((alg, value.clone())),
                         )?);
 
@@ -615,14 +653,14 @@
                 let path = TargetPath::new("batty".into()).unwrap();
                 await!(repo.store_target(data, &path)).unwrap();
 
-                let mut read = await!(repo.fetch_target(&path, &target_description, 0)).unwrap();
+                let mut read = await!(repo.fetch_target(&path, &target_description)).unwrap();
                 let mut buf = Vec::new();
                 await!(read.read_to_end(&mut buf)).unwrap();
                 assert_eq!(buf.as_slice(), data);
 
                 let bad_data: &[u8] = b"you're in a desert";
                 await!(repo.store_target(bad_data, &path)).unwrap();
-                let mut read = await!(repo.fetch_target(&path, &target_description, 0)).unwrap();
+                let mut read = await!(repo.fetch_target(&path, &target_description)).unwrap();
                 assert!(await!(read.read_to_end(&mut buf)).is_err());
             },
         )
@@ -664,14 +702,14 @@
                 // files in a mode that allows the file to be opened multiple times.
                 {
                     let mut read =
-                        await!(repo.fetch_target(&path, &target_description, 0)).unwrap();
+                        await!(repo.fetch_target(&path, &target_description)).unwrap();
                     await!(read.read_to_end(&mut buf)).unwrap();
                     assert_eq!(buf.as_slice(), data);
                 }
 
                 let bad_data: &[u8] = b"you're in a desert";
                 await!(repo.store_target(bad_data, &path)).unwrap();
-                let mut read = await!(repo.fetch_target(&path, &target_description, 0)).unwrap();
+                let mut read = await!(repo.fetch_target(&path, &target_description)).unwrap();
                 assert!(await!(read.read_to_end(&mut buf)).is_err());
             },
         )