Skip to content

Commit bf8553e

Browse files
authored
Ai suggest (#93)
* archive * cache
1 parent c34870e commit bf8553e

File tree

8 files changed

+96
-55
lines changed

8 files changed

+96
-55
lines changed

archive/archive.go

Lines changed: 36 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package archive
22

33
import (
4+
"bufio"
5+
"bytes"
46
"errors"
5-
"os"
7+
"io"
68
)
79

810
// Format represents the archive format.
@@ -15,9 +17,31 @@ const (
1517
TAR
1618
)
1719

20+
type format struct {
21+
format Format
22+
magic string
23+
}
24+
25+
var formats = []format{
26+
{ZIP, zipMagic},
27+
{TAR, tarMagic},
28+
}
29+
1830
// ErrFormat indicates that encountered an unknown format.
1931
var ErrFormat = errors.New("unknown format")
2032

33+
type reader interface {
34+
io.Reader
35+
Peek(int) ([]byte, error)
36+
}
37+
38+
func asReader(r io.Reader) reader {
39+
if rr, ok := r.(reader); ok {
40+
return rr
41+
}
42+
return bufio.NewReader(r)
43+
}
44+
2145
func match(magic string, b []byte) bool {
2246
if len(magic) != len(b) {
2347
return false
@@ -30,34 +54,24 @@ func match(magic string, b []byte) bool {
3054
return true
3155
}
3256

33-
// IsArchive tests b is an archive file or not, if ok also return its format.
34-
func IsArchive(b []byte) (bool, Format) {
35-
l := len(b)
36-
if zip := len(zipMagic); l >= zip && match(zipMagic, b[:zip]) {
37-
return true, ZIP
38-
} else if tar := len(tarMagic); l >= tar && match(tarMagic, b[:tar]) {
39-
return true, TAR
57+
func isArchive(r reader) (bool, Format) {
58+
for _, f := range formats {
59+
b, err := r.Peek(len(f.magic))
60+
if err == nil && match(f.magic, b) {
61+
return true, f.format
62+
}
4063
}
41-
4264
return false, -1
4365
}
4466

67+
// IsArchive tests b is an archive file or not, if ok also return its format.
68+
func IsArchive(b []byte) (bool, Format) {
69+
return isArchive(asReader(bytes.NewReader(b)))
70+
}
71+
4572
// File struct contains bytes body and the provided name field.
4673
type File struct {
4774
Name string
4875
Body []byte
4976
IsDir bool
5077
}
51-
52-
func readFiles(files ...string) (fs []File, err error) {
53-
for _, f := range files {
54-
var file File
55-
file.Name = f
56-
file.Body, err = os.ReadFile(f)
57-
if err != nil {
58-
return
59-
}
60-
fs = append(fs, file)
61-
}
62-
return
63-
}

archive/pack.go

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
package archive
22

33
import (
4-
"errors"
54
"io"
5+
"os"
66
)
77

88
// Pack creates an archive from File struct.
@@ -13,7 +13,7 @@ func Pack(w io.Writer, format Format, files ...File) error {
1313
case TAR:
1414
return packTar(w, files...)
1515
default:
16-
return errors.New("unknown format")
16+
return ErrFormat
1717
}
1818
}
1919

@@ -25,3 +25,16 @@ func PackFromFiles(w io.Writer, format Format, files ...string) error {
2525
}
2626
return Pack(w, format, fs...)
2727
}
28+
29+
func readFiles(files ...string) (fs []File, err error) {
30+
for _, f := range files {
31+
var file File
32+
file.Name = f
33+
file.Body, err = os.ReadFile(f)
34+
if err != nil {
35+
return
36+
}
37+
fs = append(fs, file)
38+
}
39+
return
40+
}

archive/tar.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ func packTar(w io.Writer, files ...File) error {
3535
return gw.Close()
3636
}
3737

38-
func unpackTar(b []byte) ([]File, error) {
39-
gr, err := gzip.NewReader(bytes.NewReader(b))
38+
func unpackTar(r io.Reader) ([]File, error) {
39+
gr, err := gzip.NewReader(r)
4040
if err != nil {
4141
return nil, err
4242
}

archive/unpack.go

Lines changed: 24 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package archive
22

33
import (
4+
"bytes"
45
"fmt"
56
"io"
67
"os"
@@ -9,17 +10,33 @@ import (
910

1011
// Unpack decompresses an archive to File struct.
1112
func Unpack(r io.Reader) ([]File, error) {
12-
b, err := io.ReadAll(r)
13-
if err != nil {
14-
return nil, err
13+
var ra io.ReaderAt
14+
var size int64
15+
if f, ok := r.(*os.File); ok {
16+
stat, err := f.Stat()
17+
if err != nil {
18+
return nil, err
19+
}
20+
ra = f
21+
size = stat.Size()
22+
} else if r, ok := r.(*bytes.Reader); ok {
23+
ra = r
24+
size = r.Size()
1525
}
16-
17-
_, format := IsArchive(b)
26+
rr := asReader(r)
27+
_, format := isArchive(rr)
1828
switch format {
1929
case ZIP:
20-
return unpackZip(b)
30+
if ra != nil {
31+
return unpackZip(ra, size)
32+
}
33+
b, err := io.ReadAll(rr)
34+
if err != nil {
35+
return nil, err
36+
}
37+
return unpackZip(bytes.NewReader(b), int64(len(b)))
2138
case TAR:
22-
return unpackTar(b)
39+
return unpackTar(rr)
2340
default:
2441
return nil, ErrFormat
2542
}

archive/zip.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ func packZip(w io.Writer, files ...File) error {
2525
return zw.Close()
2626
}
2727

28-
func unpackZip(b []byte) ([]File, error) {
29-
r, err := zip.NewReader(bytes.NewReader(b), int64(len(b)))
28+
func unpackZip(r io.ReaderAt, size int64) ([]File, error) {
29+
zr, err := zip.NewReader(r, size)
3030
if err != nil {
3131
return nil, err
3232
}
3333

3434
var fs []File
35-
for _, f := range r.File {
35+
for _, f := range zr.File {
3636
switch {
3737
case f.FileInfo().IsDir():
3838
fs = append(fs, File{Name: f.Name, IsDir: true})

cache/cache.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ type Cache[Key any, Value any] struct {
1313
}
1414

1515
// New creates a new cache with auto clean or not.
16-
func New[Key comparable, Value any]() *Cache[Key, Value] {
16+
func New[Key any, Value any]() *Cache[Key, Value] {
1717
return &Cache[Key, Value]{}
1818
}
1919

cache/cache_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package cache
33
import (
44
"runtime"
55
"testing"
6+
"time"
67
"weak"
78
)
89

@@ -34,6 +35,7 @@ func TestCache(t *testing.T) {
3435
t.Fatalf("expected %q, got %q", value, v)
3536
}
3637
runtime.GC()
38+
time.Sleep(time.Second)
3739
if _, ok := cache.m.Load(p); ok {
3840
t.Fatal("expected not cached, got cached")
3941
}

cache/renew.go

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,24 +9,21 @@ import (
99
"github.com/sunshineplan/utils/container"
1010
)
1111

12-
var valueKey int
13-
1412
type item[T any] struct {
1513
sync.Mutex
1614
ctx context.Context
1715
cancel context.CancelFunc
1816
lifecycle time.Duration
17+
value T
1918
fn func() (T, error)
2019
}
2120

22-
func (i *item[T]) set(value *T) {
23-
if i.ctx = context.WithValue(context.Background(), &valueKey, value); i.lifecycle > 0 {
21+
func (i *item[T]) set(value T) {
22+
i.ctx = context.Background()
23+
if i.lifecycle > 0 {
2424
i.ctx, i.cancel = context.WithTimeout(i.ctx, i.lifecycle)
2525
}
26-
}
27-
28-
func (i *item[T]) value() T {
29-
return *i.ctx.Value(&valueKey).(*T)
26+
i.value = value
3027
}
3128

3229
func (i *item[T]) renew() T {
@@ -35,9 +32,9 @@ func (i *item[T]) renew() T {
3532
defer i.Unlock()
3633
if err != nil {
3734
log.Print(err)
38-
v = i.value()
35+
v = i.value
3936
}
40-
i.set(&v)
37+
i.set(v)
4138
return v
4239
}
4340

@@ -55,9 +52,7 @@ func NewWithRenew[Key comparable, Value any](autoRenew bool) *CacheWithRenew[Key
5552
// Set sets cache value for a key, if fn is presented, this value will regenerate when expired.
5653
func (c *CacheWithRenew[Key, Value]) Set(key Key, value Value, lifecycle time.Duration, fn func() (Value, error)) {
5754
i := &item[Value]{lifecycle: lifecycle, fn: fn}
58-
i.Lock()
59-
defer i.Unlock()
60-
i.set(&value)
55+
i.set(value)
6156
if c.autoRenew && lifecycle > 0 {
6257
go func() {
6358
for {
@@ -99,7 +94,7 @@ func (c *CacheWithRenew[Key, Value]) Get(key Key) (value Value, ok bool) {
9994
}
10095
i.Lock()
10196
defer i.Unlock()
102-
value = i.value()
97+
value = i.value
10398
return
10499
}
105100

@@ -120,16 +115,16 @@ func (c *CacheWithRenew[Key, Value]) Swap(key Key, value Value) (previous Value,
120115
if i, loaded = c.get(key); loaded {
121116
i.Lock()
122117
defer i.Unlock()
123-
previous = i.value()
124-
i.set(&value)
118+
previous = i.value
119+
i.set(value)
125120
}
126121
return
127122
}
128123

129124
// Clear deletes all values in cache.
130125
func (c *CacheWithRenew[Key, Value]) Clear() {
131-
c.m.Range(func(k Key, i *item[Value]) bool {
132-
c.m.Delete(k)
126+
c.m.Range(func(key Key, i *item[Value]) bool {
127+
c.m.Delete(key)
133128
i.Lock()
134129
defer i.Unlock()
135130
if i.cancel != nil {

0 commit comments

Comments
 (0)