Sfoglia il codice sorgente

Updating Godep to pull in Set functionality

Signed-off-by: Madhu Venugopal <madhu@docker.com>
Madhu Venugopal 10 anni fa
parent
commit
ef1293ce5a

+ 7 - 2
libnetwork/Godeps/Godeps.json

@@ -20,6 +20,11 @@
 			"Comment": "v2.0.0-7-g73a8ef7",
 			"Rev": "73a8ef737e8ea002281a28b4cb92a1de121ad4c6"
 		},
+		{
+			"ImportPath": "github.com/deckarep/golang-set",
+			"Comment": "v1-26-gef32fa3",
+			"Rev": "ef32fa3046d9f249d399f98ebaf9be944430fd1d"
+		},
 		{
 			"ImportPath": "github.com/docker/docker/pkg/homedir",
 			"Comment": "v1.4.1-3479-ga9172f5",
@@ -92,8 +97,8 @@
 		{
 			"ImportPath": "github.com/gorilla/mux",
 			"Rev": "8096f47503459bcc74d1f4c487b7e6e42e5746b5"
-                },
-                {
+		},
+		{
 			"ImportPath": "github.com/hashicorp/consul/api",
 			"Comment": "v0.5.0rc1-66-g954aec6",
 			"Rev": "954aec66231b79c161a4122b023fbcad13047f79"

+ 22 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/.gitignore

@@ -0,0 +1,22 @@
+# Compiled Object files, Static and Dynamic libs (Shared Objects)
+*.o
+*.a
+*.so
+
+# Folders
+_obj
+_test
+
+# Architecture specific extensions/prefixes
+*.[568vq]
+[568vq].out
+
+*.cgo1.go
+*.cgo2.c
+_cgo_defun.c
+_cgo_gotypes.go
+_cgo_export.*
+
+_testmain.go
+
+*.exe

+ 9 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/.travis.yml

@@ -0,0 +1,9 @@
+language: go
+
+go:
+    - 1.2
+
+script:
+    - go test ./...
+    #- go test -race ./...
+

+ 22 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/LICENSE

@@ -0,0 +1,22 @@
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

+ 94 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/README.md

@@ -0,0 +1,94 @@
+[![Build Status](https://travis-ci.org/deckarep/golang-set.png?branch=master)](https://travis-ci.org/deckarep/golang-set)
+[![GoDoc](https://godoc.org/github.com/deckarep/golang-set?status.png)](http://godoc.org/github.com/deckarep/golang-set)
+
+## golang-set
+
+
+The missing set collection for the Go language.  Until Go has sets built-in...use this.
+
+Coming from Python one of the things I miss is the superbly wonderful set collection.  This is my attempt to mimic the primary features of the set from Python.
+You can of course argue that there is no need for a set in Go, otherwise the creators would have added one to the standard library.  To those I say simply ignore this repository
+and carry-on and to the rest that find this useful please contribute in helping me make it better by:
+
+* Helping to make more idiomatic improvements to the code.
+* Helping to increase the performance of it. ~~(So far, no attempt has been made, but since it uses a map internally, I expect it to be mostly performant.)~~
+* Helping to make the unit-tests more robust and kick-ass.
+* Helping to fill in the [documentation.](http://godoc.org/github.com/deckarep/golang-set)
+* Simply offering feedback and suggestions.  (Positive, constructive feedback is appreciated.)
+
+I have to give some credit for helping seed the idea with this post on [stackoverflow.](http://programmers.stackexchange.com/questions/177428/sets-data-structure-in-golang)
+
+*Update* - as of 3/9/2014, you can use a compile-time generic version of this package in the [gen](http://clipperhouse.github.io/gen/) framework.  This framework allows you to use the golang-set in a completely generic and type-safe way by allowing you to generate a supporting .go file based on your custom types.
+
+## Features (as of 9/22/2014)
+
+* a CartesionProduct() method has been added with unit-tests: [Read more about the cartesion product](http://en.wikipedia.org/wiki/Cartesian_product)
+
+## Features (as of 9/15/2014)
+
+* a PowerSet() method has been added with unit-tests: [Read more about the Power set](http://en.wikipedia.org/wiki/Power_set)
+
+## Features (as of 4/22/2014)
+
+* One common interface to both implementations
+* Two set implementations to choose from
+  * a thread-safe implementation designed for concurrent use
+  * a non-thread-safe implementation designed for performance
+* 75 benchmarks for both implementations
+* 35 unit tests for both implementations
+* 14 concurrent tests for the thread-safe implementation
+
+
+
+Please see the unit test file for additional usage examples.  The Python set documentation will also do a better job than I can of explaining how a set typically [works.](http://docs.python.org/2/library/sets.html)    Please keep in mind
+however that the Python set is a built-in type and supports additional features and syntax that make it awesome.
+
+## Examples but not exhaustive:
+
+```go
+requiredClasses := mapset.NewSet()
+requiredClasses.Add("Cooking")
+requiredClasses.Add("English")
+requiredClasses.Add("Math")
+requiredClasses.Add("Biology")
+
+scienceSlice := []interface{}{"Biology", "Chemistry"}
+scienceClasses := mapset.NewSetFromSlice(scienceSlice)
+
+electiveClasses := mapset.NewSet()
+electiveClasses.Add("Welding")
+electiveClasses.Add("Music")
+electiveClasses.Add("Automotive")
+
+bonusClasses := mapset.NewSet()
+bonusClasses.Add("Go Programming")
+bonusClasses.Add("Python Programming")
+
+//Show me all the available classes I can take
+allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses)
+fmt.Println(allClasses) //Set{Cooking, English, Math, Chemistry, Welding, Biology, Music, Automotive, Go Programming, Python Programming}
+
+
+//Is cooking considered a science class?
+fmt.Println(scienceClasses.Contains("Cooking")) //false
+
+//Show me all classes that are not science classes, since I hate science.
+fmt.Println(allClasses.Difference(scienceClasses)) //Set{Music, Automotive, Go Programming, Python Programming, Cooking, English, Math, Welding}
+
+//Which science classes are also required classes?
+fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology}
+
+//How many bonus classes do you offer?
+fmt.Println(bonusClasses.Cardinality()) //2
+
+//Do you have the following classes? Welding, Automotive and English?
+fmt.Println(allClasses.IsSuperset(mapset.NewSetFromSlice([]interface{}{"Welding", "Automotive", "English"}))) //true
+```
+
+Thanks!
+
+-Ralph
+
+[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/deckarep/golang-set/trend.png)](https://bitdeli.com/free "Bitdeli Badge")
+
+[![Analytics](https://ga-beacon.appspot.com/UA-42584447-2/deckarep/golang-set)](https://github.com/igrigorik/ga-beacon)

+ 523 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/bench_test.go

@@ -0,0 +1,523 @@
+package mapset
+
+import (
+	"math/rand"
+	"testing"
+)
+
+func nrand(n int) []int {
+	i := make([]int, n)
+	for ind := range i {
+		i[ind] = rand.Int()
+	}
+	return i
+}
+
+func toInterfaces(i []int) []interface{} {
+	ifs := make([]interface{}, len(i))
+	for ind, v := range i {
+		ifs[ind] = v
+	}
+	return ifs
+}
+
+func benchAdd(b *testing.B, s Set) {
+	nums := nrand(b.N)
+	b.ResetTimer()
+	for _, v := range nums {
+		s.Add(v)
+	}
+}
+
+func BenchmarkAddSafe(b *testing.B) {
+	benchAdd(b, NewSet())
+}
+
+func BenchmarkAddUnsafe(b *testing.B) {
+	benchAdd(b, NewThreadUnsafeSet())
+}
+
+func benchRemove(b *testing.B, s Set) {
+	nums := nrand(b.N)
+	for _, v := range nums {
+		s.Add(v)
+	}
+
+	b.ResetTimer()
+	for _, v := range nums {
+		s.Remove(v)
+	}
+}
+
+func BenchmarkRemoveSafe(b *testing.B) {
+	benchRemove(b, NewSet())
+}
+
+func BenchmarkRemoveUnsafe(b *testing.B) {
+	benchRemove(b, NewThreadUnsafeSet())
+}
+
+func benchCardinality(b *testing.B, s Set) {
+	for i := 0; i < b.N; i++ {
+		s.Cardinality()
+	}
+}
+
+func BenchmarkCardinalitySafe(b *testing.B) {
+	benchCardinality(b, NewSet())
+}
+
+func BenchmarkCardinalityUnsafe(b *testing.B) {
+	benchCardinality(b, NewThreadUnsafeSet())
+}
+
+func benchClear(b *testing.B, s Set) {
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.Clear()
+	}
+}
+
+func BenchmarkClearSafe(b *testing.B) {
+	benchClear(b, NewSet())
+}
+
+func BenchmarkClearUnsafe(b *testing.B) {
+	benchClear(b, NewThreadUnsafeSet())
+}
+
+func benchClone(b *testing.B, n int, s Set) {
+	nums := toInterfaces(nrand(n))
+	for _, v := range nums {
+		s.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.Clone()
+	}
+}
+
+func BenchmarkClone1Safe(b *testing.B) {
+	benchClone(b, 1, NewSet())
+}
+
+func BenchmarkClone1Unsafe(b *testing.B) {
+	benchClone(b, 1, NewThreadUnsafeSet())
+}
+
+func BenchmarkClone10Safe(b *testing.B) {
+	benchClone(b, 10, NewSet())
+}
+
+func BenchmarkClone10Unsafe(b *testing.B) {
+	benchClone(b, 10, NewThreadUnsafeSet())
+}
+
+func BenchmarkClone100Safe(b *testing.B) {
+	benchClone(b, 100, NewSet())
+}
+
+func BenchmarkClone100Unsafe(b *testing.B) {
+	benchClone(b, 100, NewThreadUnsafeSet())
+}
+
+func benchContains(b *testing.B, n int, s Set) {
+	nums := toInterfaces(nrand(n))
+	for _, v := range nums {
+		s.Add(v)
+	}
+
+	nums[n-1] = -1 // Definitely not in s
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.Contains(nums...)
+	}
+}
+
+func BenchmarkContains1Safe(b *testing.B) {
+	benchContains(b, 1, NewSet())
+}
+
+func BenchmarkContains1Unsafe(b *testing.B) {
+	benchContains(b, 1, NewThreadUnsafeSet())
+}
+
+func BenchmarkContains10Safe(b *testing.B) {
+	benchContains(b, 10, NewSet())
+}
+
+func BenchmarkContains10Unsafe(b *testing.B) {
+	benchContains(b, 10, NewThreadUnsafeSet())
+}
+
+func BenchmarkContains100Safe(b *testing.B) {
+	benchContains(b, 100, NewSet())
+}
+
+func BenchmarkContains100Unsafe(b *testing.B) {
+	benchContains(b, 100, NewThreadUnsafeSet())
+}
+
+func benchEqual(b *testing.B, n int, s, t Set) {
+	nums := nrand(n)
+	for _, v := range nums {
+		s.Add(v)
+		t.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.Equal(t)
+	}
+}
+
+func BenchmarkEqual1Safe(b *testing.B) {
+	benchEqual(b, 1, NewSet(), NewSet())
+}
+
+func BenchmarkEqual1Unsafe(b *testing.B) {
+	benchEqual(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkEqual10Safe(b *testing.B) {
+	benchEqual(b, 10, NewSet(), NewSet())
+}
+
+func BenchmarkEqual10Unsafe(b *testing.B) {
+	benchEqual(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkEqual100Safe(b *testing.B) {
+	benchEqual(b, 100, NewSet(), NewSet())
+}
+
+func BenchmarkEqual100Unsafe(b *testing.B) {
+	benchEqual(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func benchDifference(b *testing.B, n int, s, t Set) {
+	nums := nrand(n)
+	for _, v := range nums {
+		s.Add(v)
+	}
+	for _, v := range nums[:n/2] {
+		t.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.Difference(t)
+	}
+}
+
+func benchIsSubset(b *testing.B, n int, s, t Set) {
+	nums := nrand(n)
+	for _, v := range nums {
+		s.Add(v)
+		t.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.IsSubset(t)
+	}
+}
+
+func BenchmarkIsSubset1Safe(b *testing.B) {
+	benchIsSubset(b, 1, NewSet(), NewSet())
+}
+
+func BenchmarkIsSubset1Unsafe(b *testing.B) {
+	benchIsSubset(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkIsSubset10Safe(b *testing.B) {
+	benchIsSubset(b, 10, NewSet(), NewSet())
+}
+
+func BenchmarkIsSubset10Unsafe(b *testing.B) {
+	benchIsSubset(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkIsSubset100Safe(b *testing.B) {
+	benchIsSubset(b, 100, NewSet(), NewSet())
+}
+
+func BenchmarkIsSubset100Unsafe(b *testing.B) {
+	benchIsSubset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func benchIsSuperset(b *testing.B, n int, s, t Set) {
+	nums := nrand(n)
+	for _, v := range nums {
+		s.Add(v)
+		t.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.IsSuperset(t)
+	}
+}
+
+func BenchmarkIsSuperset1Safe(b *testing.B) {
+	benchIsSuperset(b, 1, NewSet(), NewSet())
+}
+
+func BenchmarkIsSuperset1Unsafe(b *testing.B) {
+	benchIsSuperset(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkIsSuperset10Safe(b *testing.B) {
+	benchIsSuperset(b, 10, NewSet(), NewSet())
+}
+
+func BenchmarkIsSuperset10Unsafe(b *testing.B) {
+	benchIsSuperset(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkIsSuperset100Safe(b *testing.B) {
+	benchIsSuperset(b, 100, NewSet(), NewSet())
+}
+
+func BenchmarkIsSuperset100Unsafe(b *testing.B) {
+	benchIsSuperset(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkDifference1Safe(b *testing.B) {
+	benchDifference(b, 1, NewSet(), NewSet())
+}
+
+func BenchmarkDifference1Unsafe(b *testing.B) {
+	benchDifference(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkDifference10Safe(b *testing.B) {
+	benchDifference(b, 10, NewSet(), NewSet())
+}
+
+func BenchmarkDifference10Unsafe(b *testing.B) {
+	benchDifference(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkDifference100Safe(b *testing.B) {
+	benchDifference(b, 100, NewSet(), NewSet())
+}
+
+func BenchmarkDifference100Unsafe(b *testing.B) {
+	benchDifference(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func benchIntersect(b *testing.B, n int, s, t Set) {
+	nums := nrand(int(float64(n) * float64(1.5)))
+	for _, v := range nums[:n] {
+		s.Add(v)
+	}
+	for _, v := range nums[n/2:] {
+		t.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.Intersect(t)
+	}
+}
+
+func BenchmarkIntersect1Safe(b *testing.B) {
+	benchIntersect(b, 1, NewSet(), NewSet())
+}
+
+func BenchmarkIntersect1Unsafe(b *testing.B) {
+	benchIntersect(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkIntersect10Safe(b *testing.B) {
+	benchIntersect(b, 10, NewSet(), NewSet())
+}
+
+func BenchmarkIntersect10Unsafe(b *testing.B) {
+	benchIntersect(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkIntersect100Safe(b *testing.B) {
+	benchIntersect(b, 100, NewSet(), NewSet())
+}
+
+func BenchmarkIntersect100Unsafe(b *testing.B) {
+	benchIntersect(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func benchSymmetricDifference(b *testing.B, n int, s, t Set) {
+	nums := nrand(int(float64(n) * float64(1.5)))
+	for _, v := range nums[:n] {
+		s.Add(v)
+	}
+	for _, v := range nums[n/2:] {
+		t.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.SymmetricDifference(t)
+	}
+}
+
+func BenchmarkSymmetricDifference1Safe(b *testing.B) {
+	benchSymmetricDifference(b, 1, NewSet(), NewSet())
+}
+
+func BenchmarkSymmetricDifference1Unsafe(b *testing.B) {
+	benchSymmetricDifference(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkSymmetricDifference10Safe(b *testing.B) {
+	benchSymmetricDifference(b, 10, NewSet(), NewSet())
+}
+
+func BenchmarkSymmetricDifference10Unsafe(b *testing.B) {
+	benchSymmetricDifference(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkSymmetricDifference100Safe(b *testing.B) {
+	benchSymmetricDifference(b, 100, NewSet(), NewSet())
+}
+
+func BenchmarkSymmetricDifference100Unsafe(b *testing.B) {
+	benchSymmetricDifference(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func benchUnion(b *testing.B, n int, s, t Set) {
+	nums := nrand(n)
+	for _, v := range nums[:n/2] {
+		s.Add(v)
+	}
+	for _, v := range nums[n/2:] {
+		t.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.Union(t)
+	}
+}
+
+func BenchmarkUnion1Safe(b *testing.B) {
+	benchUnion(b, 1, NewSet(), NewSet())
+}
+
+func BenchmarkUnion1Unsafe(b *testing.B) {
+	benchUnion(b, 1, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkUnion10Safe(b *testing.B) {
+	benchUnion(b, 10, NewSet(), NewSet())
+}
+
+func BenchmarkUnion10Unsafe(b *testing.B) {
+	benchUnion(b, 10, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func BenchmarkUnion100Safe(b *testing.B) {
+	benchUnion(b, 100, NewSet(), NewSet())
+}
+
+func BenchmarkUnion100Unsafe(b *testing.B) {
+	benchUnion(b, 100, NewThreadUnsafeSet(), NewThreadUnsafeSet())
+}
+
+func benchIter(b *testing.B, n int, s Set) {
+	nums := nrand(n)
+	for _, v := range nums {
+		s.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		c := s.Iter()
+		for _ = range c {
+
+		}
+	}
+}
+
+func BenchmarkIter1Safe(b *testing.B) {
+	benchIter(b, 1, NewSet())
+}
+
+func BenchmarkIter1Unsafe(b *testing.B) {
+	benchIter(b, 1, NewThreadUnsafeSet())
+}
+
+func BenchmarkIter10Safe(b *testing.B) {
+	benchIter(b, 10, NewSet())
+}
+
+func BenchmarkIter10Unsafe(b *testing.B) {
+	benchIter(b, 10, NewThreadUnsafeSet())
+}
+
+func BenchmarkIter100Safe(b *testing.B) {
+	benchIter(b, 100, NewSet())
+}
+
+func BenchmarkIter100Unsafe(b *testing.B) {
+	benchIter(b, 100, NewThreadUnsafeSet())
+}
+
+func benchString(b *testing.B, n int, s Set) {
+	nums := nrand(n)
+	for _, v := range nums {
+		s.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.String()
+	}
+}
+
+func BenchmarkString1Safe(b *testing.B) {
+	benchString(b, 1, NewSet())
+}
+
+func BenchmarkString1Unsafe(b *testing.B) {
+	benchString(b, 1, NewThreadUnsafeSet())
+}
+
+func BenchmarkString10Safe(b *testing.B) {
+	benchString(b, 10, NewSet())
+}
+
+func BenchmarkString10Unsafe(b *testing.B) {
+	benchString(b, 10, NewThreadUnsafeSet())
+}
+
+func BenchmarkString100Safe(b *testing.B) {
+	benchString(b, 100, NewSet())
+}
+
+func BenchmarkString100Unsafe(b *testing.B) {
+	benchString(b, 100, NewThreadUnsafeSet())
+}
+
+func benchToSlice(b *testing.B, s Set) {
+	nums := nrand(b.N)
+	for _, v := range nums {
+		s.Add(v)
+	}
+
+	b.ResetTimer()
+	for i := 0; i < b.N; i++ {
+		s.ToSlice()
+	}
+}
+
+func BenchmarkToSliceSafe(b *testing.B) {
+	benchToSlice(b, NewSet())
+}
+
+func BenchmarkToSliceUnsafe(b *testing.B) {
+	benchToSlice(b, NewThreadUnsafeSet())
+}

+ 168 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/set.go

@@ -0,0 +1,168 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+// Package mapset implements a simple and generic set collection.
+// Items stored within it are unordered and unique. It supports
+// typical set operations: membership testing, intersection, union,
+// difference, symmetric difference and cloning.
+//
+// Package mapset provides two implementations. The default
+// implementation is safe for concurrent access. There is a non-threadsafe
+// implementation which is slightly more performant.
+package mapset
+
+type Set interface {
+	// Adds an element to the set. Returns whether
+	// the item was added.
+	Add(i interface{}) bool
+
+	// Returns the number of elements in the set.
+	Cardinality() int
+
+	// Removes all elements from the set, leaving
+	// the emtpy set.
+	Clear()
+
+	// Returns a clone of the set using the same
+	// implementation, duplicating all keys.
+	Clone() Set
+
+	// Returns whether the given items
+	// are all in the set.
+	Contains(i ...interface{}) bool
+
+	// Returns the difference between this set
+	// and other. The returned set will contain
+	// all elements of this set that are not also
+	// elements of other.
+	//
+	// Note that the argument to Difference
+	// must be of the same type as the receiver
+	// of the method. Otherwise, Difference will
+	// panic.
+	Difference(other Set) Set
+
+	// Determines if two sets are equal to each
+	// other. If they have the same cardinality
+	// and contain the same elements, they are
+	// considered equal. The order in which
+	// the elements were added is irrelevant.
+	//
+	// Note that the argument to Equal must be
+	// of the same type as the receiver of the
+	// method. Otherwise, Equal will panic.
+	Equal(other Set) bool
+
+	// Returns a new set containing only the elements
+	// that exist only in both sets.
+	//
+	// Note that the argument to Intersect
+	// must be of the same type as the receiver
+	// of the method. Otherwise, Intersect will
+	// panic.
+	Intersect(other Set) Set
+
+	// Determines if every element in the other set
+	// is in this set.
+	//
+	// Note that the argument to IsSubset
+	// must be of the same type as the receiver
+	// of the method. Otherwise, IsSubset will
+	// panic.
+	IsSubset(other Set) bool
+
+	// Determines if every element in this set is in
+	// the other set.
+	//
+	// Note that the argument to IsSuperset
+	// must be of the same type as the receiver
+	// of the method. Otherwise, IsSuperset will
+	// panic.
+	IsSuperset(other Set) bool
+
+	// Returns a channel of elements that you can
+	// range over.
+	Iter() <-chan interface{}
+
+	// Remove a single element from the set.
+	Remove(i interface{})
+
+	// Provides a convenient string representation
+	// of the current state of the set.
+	String() string
+
+	// Returns a new set with all elements which are
+	// in either this set or the other set but not in both.
+	//
+	// Note that the argument to SymmetricDifference
+	// must be of the same type as the receiver
+	// of the method. Otherwise, SymmetricDifference
+	// will panic.
+	SymmetricDifference(other Set) Set
+
+	// Returns a new set with all elements in both sets.
+	//
+	// Note that the argument to Union must be of the
+	// same type as the receiver of the method.
+	// Otherwise, IsSuperset will panic.
+	Union(other Set) Set
+
+	// Returns all subsets of a given set (Power Set).
+	PowerSet() Set
+
+	// Returns the Cartesian Product of two sets.
+	CartesianProduct(other Set) Set
+
+	// Returns the members of the set as a slice.
+	ToSlice() []interface{}
+}
+
+// Creates and returns a reference to an empty set.
+func NewSet() Set {
+	set := newThreadSafeSet()
+	return &set
+}
+
+// Creates and returns a reference to a set from an existing slice
+func NewSetFromSlice(s []interface{}) Set {
+	a := NewSet()
+	for _, item := range s {
+		a.Add(item)
+	}
+	return a
+}
+
+func NewThreadUnsafeSet() Set {
+	set := newThreadUnsafeSet()
+	return &set
+}
+
+func NewThreadUnsafeSetFromSlice(s []interface{}) Set {
+	a := NewThreadUnsafeSet()
+	for _, item := range s {
+		a.Add(item)
+	}
+	return a
+}

+ 910 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/set_test.go

@@ -0,0 +1,910 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package mapset
+
+import "testing"
+
+func makeSet(ints []int) Set {
+	set := NewSet()
+	for _, i := range ints {
+		set.Add(i)
+	}
+	return set
+}
+
+func makeUnsafeSet(ints []int) Set {
+	set := NewThreadUnsafeSet()
+	for _, i := range ints {
+		set.Add(i)
+	}
+	return set
+}
+
+func Test_NewSet(t *testing.T) {
+	a := NewSet()
+
+	if a.Cardinality() != 0 {
+		t.Error("NewSet should start out as an empty set")
+	}
+}
+
+func Test_NewUnsafeSet(t *testing.T) {
+	a := NewThreadUnsafeSet()
+
+	if a.Cardinality() != 0 {
+		t.Error("NewSet should start out as an empty set")
+	}
+}
+
+func Test_AddSet(t *testing.T) {
+	a := makeSet([]int{1, 2, 3})
+
+	if a.Cardinality() != 3 {
+		t.Error("AddSet does not have a size of 3 even though 3 items were added to a new set")
+	}
+}
+
+func Test_AddUnsafeSet(t *testing.T) {
+	a := makeUnsafeSet([]int{1, 2, 3})
+
+	if a.Cardinality() != 3 {
+		t.Error("AddSet does not have a size of 3 even though 3 items were added to a new set")
+	}
+}
+
+func Test_AddSetNoDuplicate(t *testing.T) {
+	a := makeSet([]int{7, 5, 3, 7})
+
+	if a.Cardinality() != 3 {
+		t.Error("AddSetNoDuplicate set should have 3 elements since 7 is a duplicate")
+	}
+
+	if !(a.Contains(7) && a.Contains(5) && a.Contains(3)) {
+		t.Error("AddSetNoDuplicate set should have a 7, 5, and 3 in it.")
+	}
+}
+
+func Test_AddUnsafeSetNoDuplicate(t *testing.T) {
+	a := makeUnsafeSet([]int{7, 5, 3, 7})
+
+	if a.Cardinality() != 3 {
+		t.Error("AddSetNoDuplicate set should have 3 elements since 7 is a duplicate")
+	}
+
+	if !(a.Contains(7) && a.Contains(5) && a.Contains(3)) {
+		t.Error("AddSetNoDuplicate set should have a 7, 5, and 3 in it.")
+	}
+}
+
+func Test_RemoveSet(t *testing.T) {
+	a := makeSet([]int{6, 3, 1})
+
+	a.Remove(3)
+
+	if a.Cardinality() != 2 {
+		t.Error("RemoveSet should only have 2 items in the set")
+	}
+
+	if !(a.Contains(6) && a.Contains(1)) {
+		t.Error("RemoveSet should have only items 6 and 1 in the set")
+	}
+
+	a.Remove(6)
+	a.Remove(1)
+
+	if a.Cardinality() != 0 {
+		t.Error("RemoveSet should be an empty set after removing 6 and 1")
+	}
+}
+
+func Test_RemoveUnsafeSet(t *testing.T) {
+	a := makeUnsafeSet([]int{6, 3, 1})
+
+	a.Remove(3)
+
+	if a.Cardinality() != 2 {
+		t.Error("RemoveSet should only have 2 items in the set")
+	}
+
+	if !(a.Contains(6) && a.Contains(1)) {
+		t.Error("RemoveSet should have only items 6 and 1 in the set")
+	}
+
+	a.Remove(6)
+	a.Remove(1)
+
+	if a.Cardinality() != 0 {
+		t.Error("RemoveSet should be an empty set after removing 6 and 1")
+	}
+}
+
+func Test_ContainsSet(t *testing.T) {
+	a := NewSet()
+
+	a.Add(71)
+
+	if !a.Contains(71) {
+		t.Error("ContainsSet should contain 71")
+	}
+
+	a.Remove(71)
+
+	if a.Contains(71) {
+		t.Error("ContainsSet should not contain 71")
+	}
+
+	a.Add(13)
+	a.Add(7)
+	a.Add(1)
+
+	if !(a.Contains(13) && a.Contains(7) && a.Contains(1)) {
+		t.Error("ContainsSet should contain 13, 7, 1")
+	}
+}
+
+func Test_ContainsUnsafeSet(t *testing.T) {
+	a := NewThreadUnsafeSet()
+
+	a.Add(71)
+
+	if !a.Contains(71) {
+		t.Error("ContainsSet should contain 71")
+	}
+
+	a.Remove(71)
+
+	if a.Contains(71) {
+		t.Error("ContainsSet should not contain 71")
+	}
+
+	a.Add(13)
+	a.Add(7)
+	a.Add(1)
+
+	if !(a.Contains(13) && a.Contains(7) && a.Contains(1)) {
+		t.Error("ContainsSet should contain 13, 7, 1")
+	}
+}
+
+func Test_ContainsMultipleSet(t *testing.T) {
+	a := makeSet([]int{8, 6, 7, 5, 3, 0, 9})
+
+	if !a.Contains(8, 6, 7, 5, 3, 0, 9) {
+		t.Error("ContainsAll should contain Jenny's phone number")
+	}
+
+	if a.Contains(8, 6, 11, 5, 3, 0, 9) {
+		t.Error("ContainsAll should not have all of these numbers")
+	}
+}
+
+func Test_ContainsMultipleUnsafeSet(t *testing.T) {
+	a := makeUnsafeSet([]int{8, 6, 7, 5, 3, 0, 9})
+
+	if !a.Contains(8, 6, 7, 5, 3, 0, 9) {
+		t.Error("ContainsAll should contain Jenny's phone number")
+	}
+
+	if a.Contains(8, 6, 11, 5, 3, 0, 9) {
+		t.Error("ContainsAll should not have all of these numbers")
+	}
+}
+
+func Test_ClearSet(t *testing.T) {
+	a := makeSet([]int{2, 5, 9, 10})
+
+	a.Clear()
+
+	if a.Cardinality() != 0 {
+		t.Error("ClearSet should be an empty set")
+	}
+}
+
+func Test_ClearUnsafeSet(t *testing.T) {
+	a := makeUnsafeSet([]int{2, 5, 9, 10})
+
+	a.Clear()
+
+	if a.Cardinality() != 0 {
+		t.Error("ClearSet should be an empty set")
+	}
+}
+
+func Test_CardinalitySet(t *testing.T) {
+	a := NewSet()
+
+	if a.Cardinality() != 0 {
+		t.Error("set should be an empty set")
+	}
+
+	a.Add(1)
+
+	if a.Cardinality() != 1 {
+		t.Error("set should have a size of 1")
+	}
+
+	a.Remove(1)
+
+	if a.Cardinality() != 0 {
+		t.Error("set should be an empty set")
+	}
+
+	a.Add(9)
+
+	if a.Cardinality() != 1 {
+		t.Error("set should have a size of 1")
+	}
+
+	a.Clear()
+
+	if a.Cardinality() != 0 {
+		t.Error("set should have a size of 1")
+	}
+}
+
+func Test_CardinalityUnsafeSet(t *testing.T) {
+	a := NewThreadUnsafeSet()
+
+	if a.Cardinality() != 0 {
+		t.Error("set should be an empty set")
+	}
+
+	a.Add(1)
+
+	if a.Cardinality() != 1 {
+		t.Error("set should have a size of 1")
+	}
+
+	a.Remove(1)
+
+	if a.Cardinality() != 0 {
+		t.Error("set should be an empty set")
+	}
+
+	a.Add(9)
+
+	if a.Cardinality() != 1 {
+		t.Error("set should have a size of 1")
+	}
+
+	a.Clear()
+
+	if a.Cardinality() != 0 {
+		t.Error("set should have a size of 1")
+	}
+}
+
+func Test_SetIsSubset(t *testing.T) {
+	a := makeSet([]int{1, 2, 3, 5, 7})
+
+	b := NewSet()
+	b.Add(3)
+	b.Add(5)
+	b.Add(7)
+
+	if !b.IsSubset(a) {
+		t.Error("set b should be a subset of set a")
+	}
+
+	b.Add(72)
+
+	if b.IsSubset(a) {
+		t.Error("set b should not be a subset of set a because it contains 72 which is not in the set of a")
+	}
+}
+
+func Test_UnsafeSetIsSubset(t *testing.T) {
+	a := makeUnsafeSet([]int{1, 2, 3, 5, 7})
+
+	b := NewThreadUnsafeSet()
+	b.Add(3)
+	b.Add(5)
+	b.Add(7)
+
+	if !b.IsSubset(a) {
+		t.Error("set b should be a subset of set a")
+	}
+
+	b.Add(72)
+
+	if b.IsSubset(a) {
+		t.Error("set b should not be a subset of set a because it contains 72 which is not in the set of a")
+	}
+}
+
+func Test_SetIsSuperSet(t *testing.T) {
+	a := NewSet()
+	a.Add(9)
+	a.Add(5)
+	a.Add(2)
+	a.Add(1)
+	a.Add(11)
+
+	b := NewSet()
+	b.Add(5)
+	b.Add(2)
+	b.Add(11)
+
+	if !a.IsSuperset(b) {
+		t.Error("set a should be a superset of set b")
+	}
+
+	b.Add(42)
+
+	if a.IsSuperset(b) {
+		t.Error("set a should not be a superset of set b because set a has a 42")
+	}
+}
+
+func Test_UnsafeSetIsSuperSet(t *testing.T) {
+	a := NewThreadUnsafeSet()
+	a.Add(9)
+	a.Add(5)
+	a.Add(2)
+	a.Add(1)
+	a.Add(11)
+
+	b := NewThreadUnsafeSet()
+	b.Add(5)
+	b.Add(2)
+	b.Add(11)
+
+	if !a.IsSuperset(b) {
+		t.Error("set a should be a superset of set b")
+	}
+
+	b.Add(42)
+
+	if a.IsSuperset(b) {
+		t.Error("set a should not be a superset of set b because set a has a 42")
+	}
+}
+
+func Test_SetUnion(t *testing.T) {
+	a := NewSet()
+
+	b := NewSet()
+	b.Add(1)
+	b.Add(2)
+	b.Add(3)
+	b.Add(4)
+	b.Add(5)
+
+	c := a.Union(b)
+
+	if c.Cardinality() != 5 {
+		t.Error("set c is unioned with an empty set and therefore should have 5 elements in it")
+	}
+
+	d := NewSet()
+	d.Add(10)
+	d.Add(14)
+	d.Add(0)
+
+	e := c.Union(d)
+	if e.Cardinality() != 8 {
+		t.Error("set e should should have 8 elements in it after being unioned with set c to d")
+	}
+
+	f := NewSet()
+	f.Add(14)
+	f.Add(3)
+
+	g := f.Union(e)
+	if g.Cardinality() != 8 {
+		t.Error("set g should still ahve 8 elements in it after being unioned with set f that has duplicates")
+	}
+}
+
+func Test_UnsafeSetUnion(t *testing.T) {
+	a := NewThreadUnsafeSet()
+
+	b := NewThreadUnsafeSet()
+	b.Add(1)
+	b.Add(2)
+	b.Add(3)
+	b.Add(4)
+	b.Add(5)
+
+	c := a.Union(b)
+
+	if c.Cardinality() != 5 {
+		t.Error("set c is unioned with an empty set and therefore should have 5 elements in it")
+	}
+
+	d := NewThreadUnsafeSet()
+	d.Add(10)
+	d.Add(14)
+	d.Add(0)
+
+	e := c.Union(d)
+	if e.Cardinality() != 8 {
+		t.Error("set e should should have 8 elements in it after being unioned with set c to d")
+	}
+
+	f := NewThreadUnsafeSet()
+	f.Add(14)
+	f.Add(3)
+
+	g := f.Union(e)
+	if g.Cardinality() != 8 {
+		t.Error("set g should still ahve 8 elements in it after being unioned with set f that has duplicates")
+	}
+}
+
+func Test_SetIntersect(t *testing.T) {
+	a := NewSet()
+	a.Add(1)
+	a.Add(3)
+	a.Add(5)
+
+	b := NewSet()
+	a.Add(2)
+	a.Add(4)
+	a.Add(6)
+
+	c := a.Intersect(b)
+
+	if c.Cardinality() != 0 {
+		t.Error("set c should be the empty set because there is no common items to intersect")
+	}
+
+	a.Add(10)
+	b.Add(10)
+
+	d := a.Intersect(b)
+
+	if !(d.Cardinality() == 1 && d.Contains(10)) {
+		t.Error("set d should have a size of 1 and contain the item 10")
+	}
+}
+
+func Test_UnsafeSetIntersect(t *testing.T) {
+	a := NewThreadUnsafeSet()
+	a.Add(1)
+	a.Add(3)
+	a.Add(5)
+
+	b := NewThreadUnsafeSet()
+	a.Add(2)
+	a.Add(4)
+	a.Add(6)
+
+	c := a.Intersect(b)
+
+	if c.Cardinality() != 0 {
+		t.Error("set c should be the empty set because there is no common items to intersect")
+	}
+
+	a.Add(10)
+	b.Add(10)
+
+	d := a.Intersect(b)
+
+	if !(d.Cardinality() == 1 && d.Contains(10)) {
+		t.Error("set d should have a size of 1 and contain the item 10")
+	}
+}
+
+func Test_SetDifference(t *testing.T) {
+	a := NewSet()
+	a.Add(1)
+	a.Add(2)
+	a.Add(3)
+
+	b := NewSet()
+	b.Add(1)
+	b.Add(3)
+	b.Add(4)
+	b.Add(5)
+	b.Add(6)
+	b.Add(99)
+
+	c := a.Difference(b)
+
+	if !(c.Cardinality() == 1 && c.Contains(2)) {
+		t.Error("the difference of set a to b is the set of 1 item: 2")
+	}
+}
+
+func Test_UnsafeSetDifference(t *testing.T) {
+	a := NewThreadUnsafeSet()
+	a.Add(1)
+	a.Add(2)
+	a.Add(3)
+
+	b := NewThreadUnsafeSet()
+	b.Add(1)
+	b.Add(3)
+	b.Add(4)
+	b.Add(5)
+	b.Add(6)
+	b.Add(99)
+
+	c := a.Difference(b)
+
+	if !(c.Cardinality() == 1 && c.Contains(2)) {
+		t.Error("the difference of set a to b is the set of 1 item: 2")
+	}
+}
+
+func Test_SetSymmetricDifference(t *testing.T) {
+	a := NewSet()
+	a.Add(1)
+	a.Add(2)
+	a.Add(3)
+	a.Add(45)
+
+	b := NewSet()
+	b.Add(1)
+	b.Add(3)
+	b.Add(4)
+	b.Add(5)
+	b.Add(6)
+	b.Add(99)
+
+	c := a.SymmetricDifference(b)
+
+	if !(c.Cardinality() == 6 && c.Contains(2) && c.Contains(45) && c.Contains(4) && c.Contains(5) && c.Contains(6) && c.Contains(99)) {
+		t.Error("the symmetric difference of set a to b is the set of 6 items: 2, 45, 4, 5, 6, 99")
+	}
+}
+
+func Test_UnsafeSetSymmetricDifference(t *testing.T) {
+	a := NewThreadUnsafeSet()
+	a.Add(1)
+	a.Add(2)
+	a.Add(3)
+	a.Add(45)
+
+	b := NewThreadUnsafeSet()
+	b.Add(1)
+	b.Add(3)
+	b.Add(4)
+	b.Add(5)
+	b.Add(6)
+	b.Add(99)
+
+	c := a.SymmetricDifference(b)
+
+	if !(c.Cardinality() == 6 && c.Contains(2) && c.Contains(45) && c.Contains(4) && c.Contains(5) && c.Contains(6) && c.Contains(99)) {
+		t.Error("the symmetric difference of set a to b is the set of 6 items: 2, 45, 4, 5, 6, 99")
+	}
+}
+
+func Test_SetEqual(t *testing.T) {
+	a := NewSet()
+	b := NewSet()
+
+	if !a.Equal(b) {
+		t.Error("Both a and b are empty sets, and should be equal")
+	}
+
+	a.Add(10)
+
+	if a.Equal(b) {
+		t.Error("a should not be equal to b because b is empty and a has item 1 in it")
+	}
+
+	b.Add(10)
+
+	if !a.Equal(b) {
+		t.Error("a is now equal again to b because both have the item 10 in them")
+	}
+
+	b.Add(8)
+	b.Add(3)
+	b.Add(47)
+
+	if a.Equal(b) {
+		t.Error("b has 3 more elements in it so therefore should not be equal to a")
+	}
+
+	a.Add(8)
+	a.Add(3)
+	a.Add(47)
+
+	if !a.Equal(b) {
+		t.Error("a and b should be equal with the same number of elements")
+	}
+}
+
+func Test_UnsafeSetEqual(t *testing.T) {
+	a := NewThreadUnsafeSet()
+	b := NewThreadUnsafeSet()
+
+	if !a.Equal(b) {
+		t.Error("Both a and b are empty sets, and should be equal")
+	}
+
+	a.Add(10)
+
+	if a.Equal(b) {
+		t.Error("a should not be equal to b because b is empty and a has item 1 in it")
+	}
+
+	b.Add(10)
+
+	if !a.Equal(b) {
+		t.Error("a is now equal again to b because both have the item 10 in them")
+	}
+
+	b.Add(8)
+	b.Add(3)
+	b.Add(47)
+
+	if a.Equal(b) {
+		t.Error("b has 3 more elements in it so therefore should not be equal to a")
+	}
+
+	a.Add(8)
+	a.Add(3)
+	a.Add(47)
+
+	if !a.Equal(b) {
+		t.Error("a and b should be equal with the same number of elements")
+	}
+}
+
+func Test_SetClone(t *testing.T) {
+	a := NewSet()
+	a.Add(1)
+	a.Add(2)
+
+	b := a.Clone()
+
+	if !a.Equal(b) {
+		t.Error("Clones should be equal")
+	}
+
+	a.Add(3)
+	if a.Equal(b) {
+		t.Error("a contains one more element, they should not be equal")
+	}
+
+	c := a.Clone()
+	c.Remove(1)
+
+	if a.Equal(c) {
+		t.Error("C contains one element less, they should not be equal")
+	}
+}
+
+func Test_UnsafeSetClone(t *testing.T) {
+	a := NewThreadUnsafeSet()
+	a.Add(1)
+	a.Add(2)
+
+	b := a.Clone()
+
+	if !a.Equal(b) {
+		t.Error("Clones should be equal")
+	}
+
+	a.Add(3)
+	if a.Equal(b) {
+		t.Error("a contains one more element, they should not be equal")
+	}
+
+	c := a.Clone()
+	c.Remove(1)
+
+	if a.Equal(c) {
+		t.Error("C contains one element less, they should not be equal")
+	}
+}
+
+func Test_Iterator(t *testing.T) {
+	a := NewSet()
+
+	a.Add("Z")
+	a.Add("Y")
+	a.Add("X")
+	a.Add("W")
+
+	b := NewSet()
+	for val := range a.Iter() {
+		b.Add(val)
+	}
+
+	if !a.Equal(b) {
+		t.Error("The sets are not equal after iterating through the first set")
+	}
+}
+
+func Test_UnsafeIterator(t *testing.T) {
+	a := NewThreadUnsafeSet()
+
+	a.Add("Z")
+	a.Add("Y")
+	a.Add("X")
+	a.Add("W")
+
+	b := NewThreadUnsafeSet()
+	for val := range a.Iter() {
+		b.Add(val)
+	}
+
+	if !a.Equal(b) {
+		t.Error("The sets are not equal after iterating through the first set")
+	}
+}
+
+func Test_PowerSet(t *testing.T) {
+	a := NewThreadUnsafeSet()
+
+	a.Add(1)
+	a.Add("delta")
+	a.Add("chi")
+	a.Add(4)
+
+	b := a.PowerSet()
+	if b.Cardinality() != 16 {
+		t.Error("unexpected PowerSet cardinality")
+	}
+}
+
+func Test_EmptySetProperties(t *testing.T) {
+	empty := NewSet()
+
+	a := NewSet()
+	a.Add(1)
+	a.Add("foo")
+	a.Add("bar")
+
+	b := NewSet()
+	b.Add("one")
+	b.Add("two")
+	b.Add(3)
+	b.Add(4)
+
+	c := NewSet()
+
+	if !empty.IsSubset(a) || !empty.IsSubset(b) {
+		t.Error("The empty set is supposed to be a subset of all sets")
+	}
+
+	if !a.IsSuperset(empty) || !b.IsSuperset(empty) {
+		t.Error("All sets are supposed to be a superset of the empty set")
+	}
+
+	if !empty.IsSubset(empty) || !empty.IsSuperset(empty) {
+		t.Error("The empty set is supposed to be a subset and a superset of itself")
+	}
+
+	c = a.Union(empty)
+	if !c.Equal(a) {
+		t.Error("The union of any set with the empty set is supposed to be equal to itself")
+	}
+
+	c = a.Intersect(empty)
+	if !c.Equal(empty) {
+		t.Error("The intesection of any set with the empty set is supposed to be the empty set")
+	}
+
+	c = a.CartesianProduct(empty)
+	if c.Cardinality() != 0 {
+		t.Error("Cartesian product of any set and the empty set must be the empty set")
+	}
+
+	if empty.Cardinality() != 0 {
+		t.Error("Cardinality of the empty set is supposed to be zero")
+	}
+
+	c = empty.PowerSet()
+	if c.Cardinality() != 1 {
+		t.Error("Cardinality of the power set of the empty set is supposed to be one { {} }")
+	}
+}
+
+func Test_CartesianProduct(t *testing.T) {
+	a := NewThreadUnsafeSet()
+	b := NewThreadUnsafeSet()
+	empty := NewThreadUnsafeSet()
+
+	a.Add(1)
+	a.Add(2)
+	a.Add(3)
+
+	b.Add("one")
+	b.Add("two")
+	b.Add("three")
+	b.Add("alpha")
+	b.Add("gamma")
+
+	c := a.CartesianProduct(b)
+	d := b.CartesianProduct(a)
+
+	if c.Cardinality() != d.Cardinality() {
+		t.Error("Cardinality of AxB must be equal to BxA")
+	}
+
+	if c.Cardinality() != (a.Cardinality() * b.Cardinality()) {
+		t.Error("Unexpected cardinality for cartesian product set")
+	}
+
+	c = a.CartesianProduct(empty)
+	d = empty.CartesianProduct(b)
+
+	if c.Cardinality() != 0 || d.Cardinality() != 0 {
+		t.Error("Cartesian product of any set and the emtpy set Ax0 || 0xA must be the empty set")
+	}
+}
+
+func Test_ToSliceUnthreadsafe(t *testing.T) {
+	s := makeUnsafeSet([]int{1, 2, 3})
+	setAsSlice := s.ToSlice()
+	if len(setAsSlice) != s.Cardinality() {
+		t.Errorf("Set length is incorrect: %v", len(setAsSlice))
+	}
+
+	for _, i := range setAsSlice {
+		if !s.Contains(i) {
+			t.Errorf("Set is missing element: %v", i)
+		}
+	}
+}
+
+func Test_Example(t *testing.T) {
+	/*
+	   requiredClasses := NewSet()
+	   requiredClasses.Add("Cooking")
+	   requiredClasses.Add("English")
+	   requiredClasses.Add("Math")
+	   requiredClasses.Add("Biology")
+
+	   scienceSlice := []interface{}{"Biology", "Chemistry"}
+	   scienceClasses := NewSetFromSlice(scienceSlice)
+
+	   electiveClasses := NewSet()
+	   electiveClasses.Add("Welding")
+	   electiveClasses.Add("Music")
+	   electiveClasses.Add("Automotive")
+
+	   bonusClasses := NewSet()
+	   bonusClasses.Add("Go Programming")
+	   bonusClasses.Add("Python Programming")
+
+	   //Show me all the available classes I can take
+	   allClasses := requiredClasses.Union(scienceClasses).Union(electiveClasses).Union(bonusClasses)
+	   fmt.Println(allClasses) //Set{English, Chemistry, Automotive, Cooking, Math, Biology, Welding, Music, Go Programming}
+
+	   //Is cooking considered a science class?
+	   fmt.Println(scienceClasses.Contains("Cooking")) //false
+
+	   //Show me all classes that are not science classes, since I hate science.
+	   fmt.Println(allClasses.Difference(scienceClasses)) //Set{English, Automotive, Cooking, Math, Welding, Music, Go Programming}
+
+	   //Which science classes are also required classes?
+	   fmt.Println(scienceClasses.Intersect(requiredClasses)) //Set{Biology}
+
+	   //How many bonus classes do you offer?
+	   fmt.Println(bonusClasses.Cardinality()) //2
+
+	   //Do you have the following classes? Welding, Automotive and English?
+	   fmt.Println(allClasses.ContainsAll("Welding", "Automotive", "English"))
+	*/
+}

+ 204 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/threadsafe.go

@@ -0,0 +1,204 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package mapset
+
+import "sync"
+
+type threadSafeSet struct {
+	s threadUnsafeSet
+	sync.RWMutex
+}
+
+func newThreadSafeSet() threadSafeSet {
+	return threadSafeSet{s: newThreadUnsafeSet()}
+}
+
+func (set *threadSafeSet) Add(i interface{}) bool {
+	set.Lock()
+	ret := set.s.Add(i)
+	set.Unlock()
+	return ret
+}
+
+func (set *threadSafeSet) Contains(i ...interface{}) bool {
+	set.RLock()
+	ret := set.s.Contains(i...)
+	set.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) IsSubset(other Set) bool {
+	o := other.(*threadSafeSet)
+
+	set.RLock()
+	o.RLock()
+
+	ret := set.s.IsSubset(&o.s)
+	set.RUnlock()
+	o.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) IsSuperset(other Set) bool {
+	return other.IsSubset(set)
+}
+
+func (set *threadSafeSet) Union(other Set) Set {
+	o := other.(*threadSafeSet)
+
+	set.RLock()
+	o.RLock()
+
+	unsafeUnion := set.s.Union(&o.s).(*threadUnsafeSet)
+	ret := &threadSafeSet{s: *unsafeUnion}
+	set.RUnlock()
+	o.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) Intersect(other Set) Set {
+	o := other.(*threadSafeSet)
+
+	set.RLock()
+	o.RLock()
+
+	unsafeIntersection := set.s.Intersect(&o.s).(*threadUnsafeSet)
+	ret := &threadSafeSet{s: *unsafeIntersection}
+	set.RUnlock()
+	o.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) Difference(other Set) Set {
+	o := other.(*threadSafeSet)
+
+	set.RLock()
+	o.RLock()
+
+	unsafeDifference := set.s.Difference(&o.s).(*threadUnsafeSet)
+	ret := &threadSafeSet{s: *unsafeDifference}
+	set.RUnlock()
+	o.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) SymmetricDifference(other Set) Set {
+	o := other.(*threadSafeSet)
+
+	unsafeDifference := set.s.SymmetricDifference(&o.s).(*threadUnsafeSet)
+	return &threadSafeSet{s: *unsafeDifference}
+}
+
+func (set *threadSafeSet) Clear() {
+	set.Lock()
+	set.s = newThreadUnsafeSet()
+	set.Unlock()
+}
+
+func (set *threadSafeSet) Remove(i interface{}) {
+	set.Lock()
+	delete(set.s, i)
+	set.Unlock()
+}
+
+func (set *threadSafeSet) Cardinality() int {
+	set.RLock()
+	defer set.RUnlock()
+	return len(set.s)
+}
+
+func (set *threadSafeSet) Iter() <-chan interface{} {
+	ch := make(chan interface{})
+	go func() {
+		set.RLock()
+
+		for elem := range set.s {
+			ch <- elem
+		}
+		close(ch)
+		set.RUnlock()
+	}()
+
+	return ch
+}
+
+func (set *threadSafeSet) Equal(other Set) bool {
+	o := other.(*threadSafeSet)
+
+	set.RLock()
+	o.RLock()
+
+	ret := set.s.Equal(&o.s)
+	set.RUnlock()
+	o.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) Clone() Set {
+	set.RLock()
+
+	unsafeClone := set.s.Clone().(*threadUnsafeSet)
+	ret := &threadSafeSet{s: *unsafeClone}
+	set.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) String() string {
+	set.RLock()
+	ret := set.s.String()
+	set.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) PowerSet() Set {
+	set.RLock()
+	ret := set.s.PowerSet()
+	set.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) CartesianProduct(other Set) Set {
+	o := other.(*threadSafeSet)
+
+	set.RLock()
+	o.RLock()
+
+	unsafeCartProduct := set.s.CartesianProduct(&o.s).(*threadUnsafeSet)
+	ret := &threadSafeSet{s: *unsafeCartProduct}
+	set.RUnlock()
+	o.RUnlock()
+	return ret
+}
+
+func (set *threadSafeSet) ToSlice() []interface{} {
+	set.RLock()
+	keys := make([]interface{}, 0, set.Cardinality())
+	for elem := range set.s {
+		keys = append(keys, elem)
+	}
+	set.RUnlock()
+	return keys
+}

+ 376 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/threadsafe_test.go

@@ -0,0 +1,376 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package mapset
+
+import (
+	"math/rand"
+	"runtime"
+	"sync"
+	"testing"
+)
+
+const N = 1000
+
+func Test_AddConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+	ints := rand.Perm(N)
+
+	var wg sync.WaitGroup
+	wg.Add(len(ints))
+	for i := 0; i < len(ints); i++ {
+		go func(i int) {
+			s.Add(i)
+			wg.Done()
+		}(i)
+	}
+
+	wg.Wait()
+	for _, i := range ints {
+		if !s.Contains(i) {
+			t.Errorf("Set is missing element: %v", i)
+		}
+	}
+}
+
+func Test_CardinalityConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+
+	var wg sync.WaitGroup
+	wg.Add(1)
+	go func() {
+		elems := s.Cardinality()
+		for i := 0; i < N; i++ {
+			newElems := s.Cardinality()
+			if newElems < elems {
+				t.Errorf("Cardinality shrunk from %v to %v", elems, newElems)
+			}
+		}
+		wg.Done()
+	}()
+
+	for i := 0; i < N; i++ {
+		s.Add(rand.Int())
+	}
+	wg.Wait()
+}
+
+func Test_ClearConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+	ints := rand.Perm(N)
+
+	var wg sync.WaitGroup
+	wg.Add(len(ints))
+	for i := 0; i < len(ints); i++ {
+		go func() {
+			s.Clear()
+			wg.Done()
+		}()
+		go func(i int) {
+			s.Add(i)
+		}(i)
+	}
+
+	wg.Wait()
+}
+
+func Test_CloneConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+	ints := rand.Perm(N)
+
+	for _, v := range ints {
+		s.Add(v)
+	}
+
+	var wg sync.WaitGroup
+	wg.Add(len(ints))
+	for i := range ints {
+		go func(i int) {
+			s.Remove(i)
+			wg.Done()
+		}(i)
+	}
+
+	s.Clone()
+}
+
+func Test_ContainsConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+	ints := rand.Perm(N)
+	interfaces := make([]interface{}, 0)
+	for _, v := range ints {
+		s.Add(v)
+		interfaces = append(interfaces, v)
+	}
+
+	var wg sync.WaitGroup
+	for _ = range ints {
+		go func() {
+			s.Contains(interfaces...)
+		}()
+	}
+	wg.Wait()
+}
+
+func Test_DifferenceConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s, ss := NewSet(), NewSet()
+	ints := rand.Perm(N)
+	interfaces := make([]interface{}, 0)
+	for _, v := range ints {
+		s.Add(v)
+		ss.Add(v)
+		interfaces = append(interfaces, v)
+	}
+
+	var wg sync.WaitGroup
+	for _ = range ints {
+		go func() {
+			s.Difference(ss)
+		}()
+	}
+	wg.Wait()
+}
+
+func Test_EqualConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s, ss := NewSet(), NewSet()
+	ints := rand.Perm(N)
+	interfaces := make([]interface{}, 0)
+	for _, v := range ints {
+		s.Add(v)
+		ss.Add(v)
+		interfaces = append(interfaces, v)
+	}
+
+	var wg sync.WaitGroup
+	for _ = range ints {
+		go func() {
+			s.Equal(ss)
+		}()
+	}
+	wg.Wait()
+}
+
+func Test_IntersectConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s, ss := NewSet(), NewSet()
+	ints := rand.Perm(N)
+	interfaces := make([]interface{}, 0)
+	for _, v := range ints {
+		s.Add(v)
+		ss.Add(v)
+		interfaces = append(interfaces, v)
+	}
+
+	var wg sync.WaitGroup
+	for _ = range ints {
+		go func() {
+			s.Intersect(ss)
+		}()
+	}
+	wg.Wait()
+}
+
+func Test_IsSubsetConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s, ss := NewSet(), NewSet()
+	ints := rand.Perm(N)
+	interfaces := make([]interface{}, 0)
+	for _, v := range ints {
+		s.Add(v)
+		ss.Add(v)
+		interfaces = append(interfaces, v)
+	}
+
+	var wg sync.WaitGroup
+	for _ = range ints {
+		go func() {
+			s.IsSubset(ss)
+		}()
+	}
+	wg.Wait()
+}
+
+func Test_IsSupersetConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s, ss := NewSet(), NewSet()
+	ints := rand.Perm(N)
+	interfaces := make([]interface{}, 0)
+	for _, v := range ints {
+		s.Add(v)
+		ss.Add(v)
+		interfaces = append(interfaces, v)
+	}
+
+	var wg sync.WaitGroup
+	for _ = range ints {
+		go func() {
+			s.IsSuperset(ss)
+		}()
+	}
+	wg.Wait()
+}
+
+func Test_IterConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+	ints := rand.Perm(N)
+	for _, v := range ints {
+		s.Add(v)
+	}
+
+	cs := make([]<-chan interface{}, 0)
+	for _ = range ints {
+		cs = append(cs, s.Iter())
+	}
+
+	c := make(chan interface{})
+	go func() {
+		for n := 0; n < len(ints)*N; {
+			for _, d := range cs {
+				select {
+				case <-d:
+					n++
+					c <- nil
+				default:
+				}
+			}
+		}
+		close(c)
+	}()
+
+	for _ = range c {
+	}
+}
+
+func Test_RemoveConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+	ints := rand.Perm(N)
+	for _, v := range ints {
+		s.Add(v)
+	}
+
+	var wg sync.WaitGroup
+	wg.Add(len(ints))
+	for _, v := range ints {
+		go func(i int) {
+			s.Remove(i)
+			wg.Done()
+		}(v)
+	}
+	wg.Wait()
+
+	if s.Cardinality() != 0 {
+		t.Errorf("Expected cardinality 0; got %v", s.Cardinality())
+	}
+}
+
+func Test_StringConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+	ints := rand.Perm(N)
+	for _, v := range ints {
+		s.Add(v)
+	}
+
+	var wg sync.WaitGroup
+	wg.Add(len(ints))
+	for _ = range ints {
+		go func() {
+			s.String()
+			wg.Done()
+		}()
+	}
+	wg.Wait()
+}
+
+func Test_SymmetricDifferenceConcurrent(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s, ss := NewSet(), NewSet()
+	ints := rand.Perm(N)
+	interfaces := make([]interface{}, 0)
+	for _, v := range ints {
+		s.Add(v)
+		ss.Add(v)
+		interfaces = append(interfaces, v)
+	}
+
+	var wg sync.WaitGroup
+	for _ = range ints {
+		go func() {
+			s.SymmetricDifference(ss)
+		}()
+	}
+	wg.Wait()
+}
+
+func Test_ToSlice(t *testing.T) {
+	runtime.GOMAXPROCS(2)
+
+	s := NewSet()
+	ints := rand.Perm(N)
+
+	var wg sync.WaitGroup
+	wg.Add(len(ints))
+	for i := 0; i < len(ints); i++ {
+		go func(i int) {
+			s.Add(i)
+			wg.Done()
+		}(i)
+	}
+
+	wg.Wait()
+	setAsSlice := s.ToSlice()
+	if len(setAsSlice) != s.Cardinality() {
+		t.Errorf("Set length is incorrect: %v", len(setAsSlice))
+	}
+
+	for _, i := range setAsSlice {
+		if !s.Contains(i) {
+			t.Errorf("Set is missing element: %v", i)
+		}
+	}
+}

+ 246 - 0
libnetwork/Godeps/_workspace/src/github.com/deckarep/golang-set/threadunsafe.go

@@ -0,0 +1,246 @@
+/*
+Open Source Initiative OSI - The MIT License (MIT):Licensing
+
+The MIT License (MIT)
+Copyright (c) 2013 Ralph Caraveo (deckarep@gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
+of the Software, and to permit persons to whom the Software is furnished to do
+so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+package mapset
+
+import (
+	"fmt"
+	"reflect"
+	"strings"
+)
+
+type threadUnsafeSet map[interface{}]struct{}
+
+type orderedPair struct {
+	first  interface{}
+	second interface{}
+}
+
+func newThreadUnsafeSet() threadUnsafeSet {
+	return make(threadUnsafeSet)
+}
+
+func (pair *orderedPair) Equal(other orderedPair) bool {
+	if pair.first == other.first &&
+		pair.second == other.second {
+		return true
+	}
+
+	return false
+}
+
+func (set *threadUnsafeSet) Add(i interface{}) bool {
+	_, found := (*set)[i]
+	(*set)[i] = struct{}{}
+	return !found //False if it existed already
+}
+
+func (set *threadUnsafeSet) Contains(i ...interface{}) bool {
+	for _, val := range i {
+		if _, ok := (*set)[val]; !ok {
+			return false
+		}
+	}
+	return true
+}
+
+func (set *threadUnsafeSet) IsSubset(other Set) bool {
+	_ = other.(*threadUnsafeSet)
+	for elem := range *set {
+		if !other.Contains(elem) {
+			return false
+		}
+	}
+	return true
+}
+
+func (set *threadUnsafeSet) IsSuperset(other Set) bool {
+	return other.IsSubset(set)
+}
+
+func (set *threadUnsafeSet) Union(other Set) Set {
+	o := other.(*threadUnsafeSet)
+
+	unionedSet := newThreadUnsafeSet()
+
+	for elem := range *set {
+		unionedSet.Add(elem)
+	}
+	for elem := range *o {
+		unionedSet.Add(elem)
+	}
+	return &unionedSet
+}
+
+func (set *threadUnsafeSet) Intersect(other Set) Set {
+	o := other.(*threadUnsafeSet)
+
+	intersection := newThreadUnsafeSet()
+	// loop over smaller set
+	if set.Cardinality() < other.Cardinality() {
+		for elem := range *set {
+			if other.Contains(elem) {
+				intersection.Add(elem)
+			}
+		}
+	} else {
+		for elem := range *o {
+			if set.Contains(elem) {
+				intersection.Add(elem)
+			}
+		}
+	}
+	return &intersection
+}
+
+func (set *threadUnsafeSet) Difference(other Set) Set {
+	_ = other.(*threadUnsafeSet)
+
+	difference := newThreadUnsafeSet()
+	for elem := range *set {
+		if !other.Contains(elem) {
+			difference.Add(elem)
+		}
+	}
+	return &difference
+}
+
+func (set *threadUnsafeSet) SymmetricDifference(other Set) Set {
+	_ = other.(*threadUnsafeSet)
+
+	aDiff := set.Difference(other)
+	bDiff := other.Difference(set)
+	return aDiff.Union(bDiff)
+}
+
+func (set *threadUnsafeSet) Clear() {
+	*set = newThreadUnsafeSet()
+}
+
+func (set *threadUnsafeSet) Remove(i interface{}) {
+	delete(*set, i)
+}
+
+func (set *threadUnsafeSet) Cardinality() int {
+	return len(*set)
+}
+
+func (set *threadUnsafeSet) Iter() <-chan interface{} {
+	ch := make(chan interface{})
+	go func() {
+		for elem := range *set {
+			ch <- elem
+		}
+		close(ch)
+	}()
+
+	return ch
+}
+
+func (set *threadUnsafeSet) Equal(other Set) bool {
+	_ = other.(*threadUnsafeSet)
+
+	if set.Cardinality() != other.Cardinality() {
+		return false
+	}
+	for elem := range *set {
+		if !other.Contains(elem) {
+			return false
+		}
+	}
+	return true
+}
+
+func (set *threadUnsafeSet) Clone() Set {
+	clonedSet := newThreadUnsafeSet()
+	for elem := range *set {
+		clonedSet.Add(elem)
+	}
+	return &clonedSet
+}
+
+func (set *threadUnsafeSet) String() string {
+	items := make([]string, 0, len(*set))
+
+	for elem := range *set {
+		items = append(items, fmt.Sprintf("%v", elem))
+	}
+	return fmt.Sprintf("Set{%s}", strings.Join(items, ", "))
+}
+
+func (pair orderedPair) String() string {
+	return fmt.Sprintf("(%v, %v)", pair.first, pair.second)
+}
+
+func (set *threadUnsafeSet) PowerSet() Set {
+	powSet := NewThreadUnsafeSet()
+	nullset := newThreadUnsafeSet()
+	powSet.Add(&nullset)
+
+	for es := range *set {
+		u := newThreadUnsafeSet()
+		j := powSet.Iter()
+		for er := range j {
+			p := newThreadUnsafeSet()
+			if reflect.TypeOf(er).Name() == "" {
+				k := er.(*threadUnsafeSet)
+				for ek := range *(k) {
+					p.Add(ek)
+				}
+			} else {
+				p.Add(er)
+			}
+			p.Add(es)
+			u.Add(&p)
+		}
+
+		powSet = powSet.Union(&u)
+	}
+
+	return powSet
+}
+
+func (set *threadUnsafeSet) CartesianProduct(other Set) Set {
+	o := other.(*threadUnsafeSet)
+	cartProduct := NewThreadUnsafeSet()
+
+	for i := range *set {
+		for j := range *o {
+			elem := orderedPair{first: i, second: j}
+			cartProduct.Add(elem)
+		}
+	}
+
+	return cartProduct
+}
+
+func (set *threadUnsafeSet) ToSlice() []interface{} {
+	keys := make([]interface{}, 0, set.Cardinality())
+	for elem := range *set {
+		keys = append(keys, elem)
+	}
+
+	return keys
+}