8 "github.com/anacrolix/libtorgo/bencode"
11 // Information specific to a single file inside the MetaInfo structure.
12 type FileInfo struct {
13 Length int64 `bencode:"length"`
14 Path []string `bencode:"path"`
17 // Load a MetaInfo from an io.Reader. Returns a non-nil error in case of
19 func Load(r io.Reader) (*MetaInfo, error) {
21 d := bencode.NewDecoder(r)
29 // Convenience function for loading a MetaInfo from a file.
30 func LoadFromFile(filename string) (*MetaInfo, error) {
31 f, err := os.Open(filename)
39 // The info dictionary.
41 PieceLength int64 `bencode:"piece length"`
42 Pieces []byte `bencode:"pieces"`
43 Name string `bencode:"name"`
44 Length int64 `bencode:"length,omitempty"`
45 Private bool `bencode:"private,omitempty"`
46 Files []FileInfo `bencode:"files,omitempty"`
49 func (me *Info) TotalLength() (ret int64) {
51 for _, fi := range me.Files {
60 func (me *Info) NumPieces() int {
61 return len(me.Pieces) / 20
64 type Piece interface {
75 func (me piece) Length() int64 {
76 if me.i == me.Info.NumPieces()-1 {
77 return me.Info.TotalLength() - int64(me.i)*me.Info.PieceLength
79 return me.Info.PieceLength
82 func (me piece) Offset() int64 {
83 return int64(me.i) * me.Info.PieceLength
86 func (me piece) Hash() []byte {
87 return me.Info.Pieces[me.i*20 : (me.i+1)*20]
90 func (me *Info) Piece(i int) piece {
94 func (i *Info) IsDir() bool {
95 return len(i.Files) != 0
98 // The files field, converted up from the old single-file in the parent info
99 // dict if necessary. This is a helper to avoid having to conditionally handle
100 // single and multi-file torrent infos.
101 func (i *Info) UpvertedFiles() []FileInfo {
102 if len(i.Files) == 0 {
105 // Callers should determine that Info.Name is the basename, and
106 // thus a regular file.
113 // The info dictionary with its hash and raw bytes exposed, as these are
114 // important to Bittorrent.
122 _ bencode.Marshaler = InfoEx{}
123 _ bencode.Unmarshaler = &InfoEx{}
126 func (this *InfoEx) UnmarshalBencode(data []byte) error {
127 this.Bytes = make([]byte, 0, len(data))
128 this.Bytes = append(this.Bytes, data...)
130 _, err := h.Write(this.Bytes)
134 this.Hash = h.Sum(nil)
135 return bencode.Unmarshal(data, &this.Info)
138 func (this InfoEx) MarshalBencode() ([]byte, error) {
139 if this.Bytes != nil {
140 return this.Bytes, nil
142 return bencode.Marshal(&this.Info)
145 type MetaInfo struct {
146 Info InfoEx `bencode:"info"`
147 Announce string `bencode:"announce"`
148 AnnounceList [][]string `bencode:"announce-list,omitempty"`
149 CreationDate int64 `bencode:"creation date,omitempty"`
150 Comment string `bencode:"comment,omitempty"`
151 CreatedBy string `bencode:"created by,omitempty"`
152 Encoding string `bencode:"encoding,omitempty"`
153 URLList interface{} `bencode:"url-list,omitempty"`