summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/shazow/rateio
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/shazow/rateio')
-rw-r--r--vendor/github.com/shazow/rateio/LICENSE21
-rw-r--r--vendor/github.com/shazow/rateio/doc.go29
-rw-r--r--vendor/github.com/shazow/rateio/limiter.go62
-rw-r--r--vendor/github.com/shazow/rateio/reader.go25
-rw-r--r--vendor/github.com/shazow/rateio/writer.go25
5 files changed, 162 insertions, 0 deletions
diff --git a/vendor/github.com/shazow/rateio/LICENSE b/vendor/github.com/shazow/rateio/LICENSE
new file mode 100644
index 00000000..19011793
--- /dev/null
+++ b/vendor/github.com/shazow/rateio/LICENSE
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2015 Andrey Petrov
+
+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.
diff --git a/vendor/github.com/shazow/rateio/doc.go b/vendor/github.com/shazow/rateio/doc.go
new file mode 100644
index 00000000..1c5e0851
--- /dev/null
+++ b/vendor/github.com/shazow/rateio/doc.go
@@ -0,0 +1,29 @@
+/*
+Package rateio provides an io interfaces for rate-limiting.
+
+This can be used to apply rate limiting to any type that implements an io-style interface.
+
+For example, we can use it to restrict the reading rate of a net.Conn:
+
+ type limitedConn struct {
+ net.Conn
+ io.Reader // Our rate-limited io.Reader for net.Conn
+ }
+
+ func (r *limitedConn) Read(p []byte) (n int, err error) {
+ return r.Reader.Read(p)
+ }
+
+ // ReadLimitConn returns a net.Conn whose io.Reader interface is rate-limited by limiter.
+ func ReadLimitConn(conn net.Conn, limiter rateio.Limiter) net.Conn {
+ return &limitedConn{
+ Conn: conn,
+ Reader: rateio.NewReader(conn, limiter),
+ }
+ }
+
+Then we can use ReadLimitConn to wrap our existing net.Conn and continue using
+the wrapped version in its place.
+
+*/
+package rateio
diff --git a/vendor/github.com/shazow/rateio/limiter.go b/vendor/github.com/shazow/rateio/limiter.go
new file mode 100644
index 00000000..db5ae76c
--- /dev/null
+++ b/vendor/github.com/shazow/rateio/limiter.go
@@ -0,0 +1,62 @@
+package rateio
+
+import (
+ "errors"
+ "time"
+)
+
+const minInt = -int(^uint(0)>>1) - 1
+
+// The error returned when the read rate exceeds our specification.
+var ErrRateExceeded = errors.New("Read rate exceeded.")
+
+// Limiter is an interface for a rate limiter.
+// There are a few example limiters included in the package, but feel free to go wild with your own.
+type Limiter interface {
+ // Apply this many bytes to the limiter, return ErrRateExceeded if the defined rate is exceeded.
+ Count(int) error
+}
+
+// simpleLimiter is a rate limiter that restricts Amount bytes in Frequency duration.
+type simpleLimiter struct {
+ Amount int
+ Frequency time.Duration
+
+ numRead int
+ timeRead time.Time
+}
+
+// NewSimpleLimiter creates a Limiter that restricts a given number of bytes per frequency.
+func NewSimpleLimiter(amount int, frequency time.Duration) Limiter {
+ return &simpleLimiter{
+ Amount: amount,
+ Frequency: frequency,
+ }
+}
+
+// NewGracefulLimiter returns a Limiter that is the same as a
+// SimpleLimiter but adds a grace period at the start of the rate
+// limiting where it allows unlimited bytes to be read during that
+// period.
+func NewGracefulLimiter(amount int, frequency time.Duration, grace time.Duration) Limiter {
+ return &simpleLimiter{
+ Amount: amount,
+ Frequency: frequency,
+ numRead: minInt,
+ timeRead: time.Now().Add(grace),
+ }
+}
+
+// Count applies n bytes to the limiter.
+func (limit *simpleLimiter) Count(n int) error {
+ now := time.Now()
+ if now.After(limit.timeRead) {
+ limit.numRead = 0
+ limit.timeRead = now.Add(limit.Frequency)
+ }
+ limit.numRead += n
+ if limit.numRead > limit.Amount {
+ return ErrRateExceeded
+ }
+ return nil
+}
diff --git a/vendor/github.com/shazow/rateio/reader.go b/vendor/github.com/shazow/rateio/reader.go
new file mode 100644
index 00000000..56bd8ffa
--- /dev/null
+++ b/vendor/github.com/shazow/rateio/reader.go
@@ -0,0 +1,25 @@
+package rateio
+
+import "io"
+
+type reader struct {
+ io.Reader
+ Limiter
+}
+
+// Read reads data into p.
+// Returns ErrRateExceeded error if our specified read is exceeded.
+func (r *reader) Read(p []byte) (n int, err error) {
+ n, err = r.Reader.Read(p)
+ if err != nil {
+ return
+ }
+
+ err = r.Limiter.Count(n)
+ return
+}
+
+// NewReader proxies an io.Reader but keeps track of bytes read based on our Limiter.
+func NewReader(r io.Reader, limiter Limiter) io.Reader {
+ return &reader{r, limiter}
+}
diff --git a/vendor/github.com/shazow/rateio/writer.go b/vendor/github.com/shazow/rateio/writer.go
new file mode 100644
index 00000000..d4feea49
--- /dev/null
+++ b/vendor/github.com/shazow/rateio/writer.go
@@ -0,0 +1,25 @@
+package rateio
+
+import "io"
+
+type writer struct {
+ io.Writer
+ Limiter
+}
+
+// Write writes the contents of p into the buffer.
+// Returns ErrRateExceeded error if our specified read is exceeded.
+func (w *writer) Write(p []byte) (n int, err error) {
+ n, err = w.Writer.Write(p)
+ if err != nil {
+ return
+ }
+
+ err = w.Limiter.Count(n)
+ return
+}
+
+// NewWriter proxies an io.Writer but keeps track of bytes read based on our Limiter.
+func NewWriter(w io.Writer, limiter Limiter) io.Writer {
+ return &writer{w, limiter}
+}