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