]> Sergey Matveev's repositories - btrtrc.git/blob - storage/wrappers.go
Rework storage interfaces to make them simpler to implement
[btrtrc.git] / storage / wrappers.go
1 package storage
2
3 import (
4         "errors"
5         "io"
6         "os"
7
8         "github.com/anacrolix/missinggo"
9
10         "github.com/anacrolix/torrent/metainfo"
11 )
12
13 type Client struct {
14         ClientImpl
15 }
16
17 func NewClient(cl ClientImpl) *Client {
18         return &Client{cl}
19 }
20
21 func (cl Client) OpenTorrent(info *metainfo.Info, infoHash metainfo.Hash) (*Torrent, error) {
22         t, err := cl.ClientImpl.OpenTorrent(info, infoHash)
23         return &Torrent{t}, err
24 }
25
26 type Torrent struct {
27         TorrentImpl
28 }
29
30 func (t Torrent) Piece(p metainfo.Piece) Piece {
31         return Piece{t.TorrentImpl.Piece(p), p}
32 }
33
34 type Piece struct {
35         PieceImpl
36         mip metainfo.Piece
37 }
38
39 func (p Piece) WriteAt(b []byte, off int64) (n int, err error) {
40         if p.GetIsComplete() {
41                 err = errors.New("piece completed")
42                 return
43         }
44         if off+int64(len(b)) > p.mip.Length() {
45                 panic("write overflows piece")
46         }
47         missinggo.LimitLen(&b, p.mip.Length()-off)
48         return p.PieceImpl.WriteAt(b, off)
49 }
50
51 func (p Piece) ReadAt(b []byte, off int64) (n int, err error) {
52         if off < 0 {
53                 err = os.ErrInvalid
54                 return
55         }
56         if off >= p.mip.Length() {
57                 err = io.EOF
58                 return
59         }
60         missinggo.LimitLen(&b, p.mip.Length()-off)
61         if len(b) == 0 {
62                 return
63         }
64         n, err = p.PieceImpl.ReadAt(b, off)
65         if n > len(b) {
66                 panic(n)
67         }
68         off += int64(n)
69         if err == io.EOF && off < p.mip.Length() {
70                 err = io.ErrUnexpectedEOF
71         }
72         if err == nil && off >= p.mip.Length() {
73                 err = io.EOF
74         }
75         if n == 0 && err == nil {
76                 err = io.ErrUnexpectedEOF
77         }
78         if off < p.mip.Length() && err != nil {
79                 p.MarkNotComplete()
80         }
81         return
82 }