Repository: cassandra-rs/cassandra-rs (language: rust)

Issue:
[0.16] rename `CassCollection::new` -> `CassCollection::with_capacity`
The size passed to `CassCollection::new(...)` is but a hint to avoid re-allocations, very similar to how the similarly named `Vec` methods work. 

This issue proposes re-naming it to `with_capacity`, and providing a `new` that just calls `with_capacity(0)`. This will clarify intent for users of the library that the size is but a hint/optimization. 

The underlying ffi we're wrapping is here: https://docs.datastax.com/en/developer/cpp-driver/2.4/api/struct.CassCollection/#function-cass_collection_new - the docs mention it as an "approximate count" - and reading into the source code of where it's eventually used, https://github.com/datastax/cpp-driver/blob/master/src/collection.hpp#L42 we can see it's just pre-sizing an array as well to avoid re-allocations. 


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 35d75a7..72d949f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,10 @@ version number is tracked in the file `VERSION`.
 - Switched to using `parking_lot::Mutex` instead of `std::sync::Mutex` for
   `CassFuture` coordination.
 - Implemented `size_hint` on `ResultIterator`.
+- `CassCollection::new` has been renamed to `CassCollection::with_capacity`, and `CassCollection::new` has
+  been created, that no longer requires a capacity. This closely mirrors the API that the standard library
+  collections expose, and that the `item_count` passed to `new` is merely a capacity hint for the purpose of
+  optimization.
 - `time::Duration` has been replaced with `std::time::Duration`.
 
 ### Fixed
diff --git a/examples/collections.rs b/examples/collections.rs
index 1d35389..42915a9 100644
--- a/examples/collections.rs
+++ b/examples/collections.rs
@@ -15,12 +15,12 @@ fn do_work(session: &Session) -> Result<()> {
 
     insert_data.bind(0, "Paul")?;
     insert_data.bind_null(1)?;
-    let mut addresses = List::new(0);
+    let mut addresses = List::new();
     addresses.append_string("george@example.com")?;
     addresses.append_string("paul@example.com")?;
     insert_data.bind(2, addresses)?;
     insert_data.bind(3, "George")?;
-    let mut phones = List::new(0);
+    let mut phones = List::new();
     phones.append_string("123-456")?;
     phones.append_string("789-012")?;
     insert_data.bind(4, phones)?; // TODO: bind should really accept Vec<T>, and map should accept HashMap<T, U>. Requires generic CassCollection::append.
diff --git a/src/cassandra/collection.rs b/src/cassandra/collection.rs
index cd5b618..96aa046 100644
--- a/src/cassandra/collection.rs
+++ b/src/cassandra/collection.rs
@@ -45,12 +45,21 @@ use std::os::raw::c_char;
 // }
 
 /// A generic Cassandra collection that needs to go away
-pub trait CassCollection {
+pub trait CassCollection: Sized {
     /// The type of value held by this collection
     type Value;
 
     /// Creates a new collection.
-    fn new(item_count: usize) -> Self;
+    fn new() -> Self {
+        Self::with_capacity(0)
+    }
+
+    /// Creates a new collection, specifying a capacity which will be
+    /// used as a size hint to avoid re-allocations of the collection internally.
+    ///
+    /// If you know the number of items you'll insert into the collection ahead of time,
+    /// it is recommended to use this function over [`CassCollection::new`].
+    fn with_capacity(capacity: usize) -> Self;
 
     /// Creates a new collection from an existing data type.
     fn new_from_data_type(value: DataType, item_count: usize) -> Self;
@@ -165,8 +174,8 @@ impl CassCollection for List {
     type Value = _CassCollection;
 
     /// create a new list
-    fn new(item_count: usize) -> Self {
-        unsafe { List::build(cass_collection_new(CASS_COLLECTION_TYPE_LIST, item_count)) }
+    fn with_capacity(capacity: usize) -> Self {
+        unsafe { List::build(cass_collection_new(CASS_COLLECTION_TYPE_LIST, capacity)) }
     }
 
     fn new_from_data_type(value: DataType, item_count: usize) -> Self {
@@ -302,8 +311,8 @@ impl CassCollection for Set {
     type Value = _CassCollection;
 
     /// create a new list
-    fn new(item_count: usize) -> Self {
-        unsafe { Set(cass_collection_new(CASS_COLLECTION_TYPE_SET, item_count)) }
+    fn with_capacity(capacity: usize) -> Self {
+        unsafe { Set(cass_collection_new(CASS_COLLECTION_TYPE_SET, capacity)) }
     }
 
     fn new_from_data_type(value: DataType, item_count: usize) -> Self {
@@ -432,9 +441,9 @@ impl Drop for Map {
 
 impl CassCollection for Map {
     type Value = _CassCollection;
-    /// create a new list
-    fn new(item_count: usize) -> Self {
-        unsafe { Map(cass_collection_new(CASS_COLLECTION_TYPE_MAP, item_count)) }
+
+    fn with_capacity(capacity: usize) -> Self {
+        unsafe { Map(cass_collection_new(CASS_COLLECTION_TYPE_MAP, capacity)) }
     }
 
     fn new_from_data_type(value: DataType, item_count: usize) -> Self {


Test patch:
diff --git a/tests/collections.rs b/tests/collections.rs
index 3a9e35c..74c9149 100644
--- a/tests/collections.rs
+++ b/tests/collections.rs
@@ -10,7 +10,7 @@ fn insert_into_collections(
 ) -> Result<CassResult> {
     let mut statement = stmt!("INSERT INTO examples.collections (key, items) VALUES (?, ?);");
     statement.bind(0, key)?;
-    let mut set = Set::new(2);
+    let mut set = Set::with_capacity(2);
     for item in items {
         set.append_string(item)?;
     }
diff --git a/tests/maps.rs b/tests/maps.rs
index d7b310b..45470d8 100644
--- a/tests/maps.rs
+++ b/tests/maps.rs
@@ -18,7 +18,7 @@ fn insert_into_maps(session: &Session, key: &str, items: &Vec<Pair>) -> Result<(
     let mut insert_statement = stmt!("INSERT INTO examples.maps (key, items) VALUES (?, ?);");
     insert_statement.bind(0, key).unwrap();
 
-    let mut map = Map::new(items.len());
+    let mut map = Map::with_capacity(items.len());
     for item in items {
         map.append_string(item.key.as_ref()).unwrap();
         map.append_int32(item.value).unwrap();