Skip to content

Commit 873ab94

Browse files
committed
initial commit
0 parents  commit 873ab94

19 files changed

+680
-0
lines changed

.github/FUNDING.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github: [samber]

.github/workflows/lint.yml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
tags:
6+
branches:
7+
pull_request:
8+
9+
jobs:
10+
golangci:
11+
name: lint
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/setup-go@v2
15+
with:
16+
go-version: 1.16
17+
stable: false
18+
- uses: actions/checkout@v2
19+
- name: golangci-lint
20+
uses: golangci/golangci-lint-action@v2
21+
with:
22+
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
23+
version: latest
24+
25+
# Optional: working directory, useful for monorepos
26+
working-directory: ./
27+
28+
# Optional: golangci-lint command line arguments.
29+
args: --timeout 60s --max-same-issues 50
30+
31+
# Optional: show only new issues if it's a pull request. The default value is `false`.
32+
# only-new-issues: true
33+
34+
# Optional: if set to true then the action will use pre-installed Go.
35+
# skip-go-installation: true
36+
37+
# Optional: if set to true then the action don't cache or restore ~/go/pkg.
38+
# skip-pkg-cache: true
39+
40+
# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
41+
# skip-build-cache: true
42+
43+
# optionally use a specific version of Go rather than the latest one
44+
go_version: '1.16'

.github/workflows/release.yml

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
name: Release
2+
3+
on:
4+
workflow_dispatch:
5+
inputs:
6+
semver:
7+
type: string
8+
description: 'Semver (eg: v1.2.3)'
9+
required: true
10+
11+
jobs:
12+
release:
13+
if: github.triggering_actor == 'samber'
14+
runs-on: ubuntu-latest
15+
steps:
16+
- uses: actions/checkout@v2
17+
18+
- name: Set up Go
19+
uses: actions/setup-go@v2
20+
with:
21+
go-version: 1.16
22+
stable: false
23+
24+
- name: Test
25+
run: make test
26+
27+
# remove tests in order to clean dependencies
28+
- name: Remove xxx_test.go files
29+
run: rm -rf *_test.go ./examples ./images
30+
31+
# cleanup test dependencies
32+
- name: Cleanup dependencies
33+
run: go mod tidy
34+
35+
- name: List files
36+
run: tree -Cfi
37+
- name: Write new go.mod into logs
38+
run: cat go.mod
39+
- name: Write new go.sum into logs
40+
run: cat go.sum
41+
42+
- name: Create tag
43+
run: |
44+
git config --global user.name '${{ github.triggering_actor }}'
45+
git config --global user.email "${{ github.triggering_actor}}@users.noreply.github.com"
46+
47+
git add .
48+
git commit --allow-empty -m 'bump ${{ inputs.semver }}'
49+
git tag ${{ inputs.semver }}
50+
git push origin ${{ inputs.semver }}
51+
52+
- name: Release
53+
uses: softprops/action-gh-release@v1
54+
with:
55+
name: ${{ inputs.semver }}
56+
tag_name: ${{ inputs.semver }}

.github/workflows/test.yml

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
name: Tests
2+
3+
on:
4+
push:
5+
tags:
6+
branches:
7+
pull_request:
8+
9+
jobs:
10+
11+
test:
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v2
15+
16+
- name: Set up Go
17+
uses: actions/setup-go@v2
18+
with:
19+
go-version: 1.16
20+
stable: false
21+
22+
- name: Build
23+
run: make build
24+
25+
- name: Test
26+
run: make test
27+
28+
- name: Test
29+
run: make coverage
30+
31+
- name: Codecov
32+
uses: codecov/codecov-action@v2
33+
with:
34+
token: ${{ secrets.CODECOV_TOKEN }}
35+
file: ./cover.out
36+
flags: unittests
37+
verbose: true

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2023 Samuel Berthe
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

Makefile

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
2+
BIN=go
3+
4+
build:
5+
${BIN} build -v ./...
6+
7+
test:
8+
go test -race -v ./...
9+
watch-test:
10+
reflex -t 50ms -s -- sh -c 'gotest -race -v ./...'
11+
12+
bench:
13+
go test -benchmem -count 3 -bench ./...
14+
watch-bench:
15+
reflex -t 50ms -s -- sh -c 'go test -benchmem -count 3 -bench ./...'
16+
17+
coverage:
18+
${BIN} test -v -coverprofile=cover.out -covermode=atomic .
19+
${BIN} tool cover -html=cover.out -o cover.html
20+
21+
tools:
22+
${BIN} install github.com/cespare/reflex@latest
23+
${BIN} install github.com/rakyll/gotest@latest
24+
${BIN} install github.com/psampaz/go-mod-outdated@latest
25+
${BIN} install github.com/jondot/goweight@latest
26+
${BIN} install github.com/golangci/golangci-lint/cmd/golangci-lint@latest
27+
${BIN} get -t -u golang.org/x/tools/cmd/cover
28+
${BIN} install github.com/sonatype-nexus-community/nancy@latest
29+
go mod tidy
30+
31+
lint:
32+
golangci-lint run --timeout 60s --max-same-issues 50 ./...
33+
lint-fix:
34+
golangci-lint run --timeout 60s --max-same-issues 50 --fix ./...
35+
36+
audit:
37+
${BIN} list -json -m all | nancy sleuth
38+
39+
outdated:
40+
${BIN} list -u -m -json all | go-mod-outdated -update -direct
41+
42+
weight:
43+
goweight

README.md

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
2+
# Metered io.Reader and io.Writer
3+
4+
[![tag](https://img.shields.io/github/tag/samber/go-metered-io.svg)](https://github.com/samber/go-metered-io/releases)
5+
![Go Version](https://img.shields.io/badge/Go-%3E%3D%201.16.0-%23007d9c)
6+
[![GoDoc](https://godoc.org/github.com/samber/go-metered-io?status.svg)](https://pkg.go.dev/github.com/samber/go-metered-io)
7+
![Build Status](https://github.com/samber/go-metered-io/actions/workflows/test.yml/badge.svg)
8+
[![Go report](https://goreportcard.com/badge/github.com/samber/go-metered-io)](https://goreportcard.com/report/github.com/samber/go-metered-io)
9+
[![Coverage](https://img.shields.io/codecov/c/github/samber/go-metered-io)](https://codecov.io/gh/samber/go-metered-io)
10+
[![Contributors](https://img.shields.io/github/contributors/samber/go-metered-io)](https://github.com/samber/go-metered-io/graphs/contributors)
11+
[![License](https://img.shields.io/github/license/samber/go-metered-io)](./LICENSE)
12+
13+
A drop-in replacement to `io.Reader` and `io.Writer` from the standard library with the total number of bytes transfered.
14+
15+
## 🚀 Install
16+
17+
```sh
18+
go get github.com/samber/go-metered-io
19+
```
20+
21+
This library is v1 and follows SemVer strictly. No breaking changes will be made to exported APIs before v2.0.0.
22+
23+
## 💡 Spec
24+
25+
GoDoc: [https://pkg.go.dev/github.com/samber/go-metered-io](https://pkg.go.dev/github.com/samber/go-metered-io)
26+
27+
Byte:
28+
- metered.NewReader
29+
- metered.NewWriter
30+
- metered.NewReadCloser
31+
- metered.NewWriteCloser
32+
- metered.NewReadWriter
33+
34+
String:
35+
- metered.NewStringWriter
36+
37+
Rune:
38+
- metered.NewRuneReader
39+
40+
## Examples
41+
42+
### Metered reader
43+
44+
```go
45+
import "github.com/samber/go-metered-io"
46+
47+
r := metered.NewReader(strings.NewReader("Lorem ipsum dolor sit amet..."))
48+
49+
for {
50+
buff := make([]byte, 10)
51+
52+
_, err := r.Read(buff)
53+
if err != nil {
54+
break
55+
}
56+
}
57+
58+
fmt.Printf("Total bytes: %d", r.Rx())
59+
```
60+
61+
### Metered writer
62+
63+
```go
64+
import "github.com/samber/go-metered-io"
65+
66+
var buf bytes.Buffer
67+
w := metered.NewWriter(&buf)
68+
69+
for i := 0 ; i < 10 ; i++ {
70+
_, err := w.Write("Hello world\n")
71+
if err != nil {
72+
break
73+
}
74+
}
75+
76+
fmt.Printf("Total bytes: %d", w.Tx())
77+
```
78+
79+
## 🤝 Contributing
80+
81+
- Ping me on twitter [@samuelberthe](https://twitter.com/samuelberthe) (DMs, mentions, whatever :))
82+
- Fork the [project](https://github.com/samber/go-metered-io)
83+
- Fix [open issues](https://github.com/samber/go-metered-io/issues) or request new features
84+
85+
Don't hesitate ;)
86+
87+
```bash
88+
# Install some dev dependencies
89+
make tools
90+
91+
# Run tests
92+
make test
93+
# or
94+
make watch-test
95+
```
96+
97+
## 👤 Contributors
98+
99+
![Contributors](https://contrib.rocks/image?repo=samber/go-metered-io)
100+
101+
## 💫 Show your support
102+
103+
Give a ⭐️ if this project helped you!
104+
105+
[![GitHub Sponsors](https://img.shields.io/github/sponsors/samber?style=for-the-badge)](https://github.com/sponsors/samber)
106+
107+
## 📝 License
108+
109+
Copyright © 2023 [Samuel Berthe](https://github.com/samber).
110+
111+
This project is [MIT](./LICENSE) licensed.

byte_read_writer.go

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package metered
2+
3+
import (
4+
"io"
5+
"sync/atomic"
6+
)
7+
8+
// Implements io.ReadWriter
9+
type ReadWriter struct {
10+
rw io.ReadWriter
11+
rx uint64
12+
tx uint64
13+
}
14+
15+
func NewReadWriter(rw io.ReadWriter) *ReadWriter {
16+
return &ReadWriter{
17+
rw: rw,
18+
}
19+
}
20+
21+
func (rw *ReadWriter) Read(p []byte) (n int, err error) {
22+
n, err = rw.rw.Read(p)
23+
atomic.AddUint64(&rw.rx, uint64(n))
24+
return
25+
}
26+
27+
func (rw *ReadWriter) Write(p []byte) (n int, err error) {
28+
n, err = rw.rw.Write(p)
29+
atomic.AddUint64(&rw.tx, uint64(n))
30+
return
31+
}
32+
33+
func (rw *ReadWriter) Rx() uint64 {
34+
return atomic.LoadUint64(&rw.rx)
35+
}
36+
37+
func (rw *ReadWriter) Tx() uint64 {
38+
return atomic.LoadUint64(&rw.tx)
39+
}
40+
41+
// Implements io.ReadWriteCloser
42+
type ReadWriteCloser struct {
43+
*ReadWriter
44+
io.Closer
45+
}
46+
47+
func NewReadWriteCloser(rw io.ReadWriteCloser) *ReadWriteCloser {
48+
return &ReadWriteCloser{
49+
ReadWriter: NewReadWriter(rw),
50+
Closer: rw,
51+
}
52+
}

0 commit comments

Comments
 (0)