summaryrefslogtreecommitdiff
path: root/src/types.zig
blob: 7ed50dcfb8cbf0031cdea37b64500cfe55e397ec (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
const std = @import("std");

const Request = @import("request.zig").Request;

// types are from:
//   https://github.com/transmission/transmission/blob/76166d8fa71f351fe46221d737f8849b23f551f7/libtransmission/transmission.h#L1604
// where:
//   time_t => i64
//   float => f32
//   uint16_t => u16
pub const Torrent = struct {
    // The last time we uploaded or downloaded piece data on this torrent.
    activityDate: ?i64 = null,

    // When the torrent was first added.
    addedDate: ?i64 = null,

    // An array of numbers representing the number of connected peers that
    // have each piece, or -1 if we already have the piece ourselves.
    availability: ?[]i64 = null,

    // ??
    bandwidthPriority: ?i8 = null,

    // ??
    comment: ?[]u8 = null,

    // Byte count of all the corrupt data you've ever downloaded for
    // this torrent. If you're on a poisoned torrent, this number can
    // grow very large.
    corruptEver: ?u64 = null,

    // ??
    creator: ?[]u8 = null,

    // ??
    dateCreated: ?i64 = null,

    // Byte count of all the piece data we want and don't have yet,
    // but that a connected peer does have.
    desiredAvailable: ?u64 = null,

    // When the torrent finished downloading.
    doneDate: ?i64 = null,

    // ??
    downloadDir: ?[]u8 = null,

    // Byte count of all the non-corrupt data you've ever downloaded
    // for this torrent. If you deleted the files and downloaded a second
    // time, this will be `2*totalSize`.
    downloadedEver: ?u64 = null,

    // TODO: ?? can't find the definition anywhere
    //downloadLimit: ?usize = null,

    downloadLimited: ?bool = null,

    // The last time during this session that a rarely-changing field
    // changed -- e.g. fields like trackers, filenames, name
    // or download directory. RPC clients can monitor this to know when
    // to reload fields that rarely change.
    editDate: ?i64 = null,

    // Defines what kind of text is in errorString.
    @"error": ?enum {
        // everything's fine
        ok,

        // when we announced to the tracker, we got a warning in the response
        tracker_warning,

        // when we announced to the tracker, we got an error in the response
        tracker_error,

        // local trouble, such as disk full or permissions error
        local_error,
    },

    // A warning or error message regarding the torrent.
    errorString: ?[]u8 = null,

    // If downloading, estimated number of seconds left until the torrent is done.
    // If seeding, estimated number of seconds left until seed ratio is reached.
    eta: ?i64 = null,

    // If seeding, number of seconds left until the idle time limit is reached.
    etaIdle: ?i64 = null,

    // ??
    @"file-count": ?usize = null,

    // ?? TODO: this is most likely outdated, the returned json is missing
    // some of the fields in the docs
    files: ?[]struct {
        bytesCompleted: ?u64 = null,
        length: ?u64 = null,
        name: ?[]u8 = null,
        beginPiece: ?u32 = null,
        endPiece: ?u32 = null,
    } = null,

    //fileStats 	array (see below) 	n/a

    group: ?[]u8 = null,
    hashString: ?[]u8 = null,

    // Byte count of all the partial piece data we have for this torrent.
    // As pieces become complete, this value may decrease as portions of it
    // are moved to `corrupt` or `haveValid`.
    haveUnchecked: ?u64 = null,

    // Byte count of all the checksum-verified data we have for this torrent.
    haveValid: ?u64 = null,

    honorsSessionLimits: ?bool = null,

    id: ?i32 = null,

    isFinished: ?bool = null,
    isPrivate: ?bool = null,
    isStalled: ?bool = null,
    labels: ?[][]u8 = null,

    // Byte count of how much data is left to be downloaded until we've got
    // all the pieces that we want.
    leftUntilDone: ?u64 = null,

    magnetLink: ?[]u8 = null,
    //manualAnnounceTime: ?usize = null,
    //maxConnectedPeers: ?usize = null,

    // How much of the metadata the torrent has.
    // For torrents added from a torrent this will always be 1.
    // For magnet links, this number will from from 0 to 1 as the metadata is downloaded.
    // Range is [0..1]
    metadataPercentComplete: ?f32 = null,

    name: ?[]u8 = null,
    //@"peer-limit": ?usize = null,
    ////peers 	array (see below) 	n/a

    // Number of peers that we're connected to
    peersConnected: ?u16 = null,

    ////peersFrom 	object (see below) 	n/a

    // Number of peers that we're sending data to.
    peersGettingFromUs: ?u16 = null,

    // Number of peers that are sending data to us.
    peersSendingToUs: ?u16 = null,

    // How much has been downloaded of the entire torrent.
    // Range is [0..1]
    percentComplete: ?f32 = null,

    // How much has been downloaded of the files the user wants. This differs
    // from percentComplete if the user wants only some of the torrent's files.
    // Range is [0..1]
    // See `leftUntilDone`
    percentDone: ?f32 = null,

    pieces: ?[]u8 = null,
    //pieceCount: ?usize = null,
    //pieceSize: ?usize = null,
    ////priorities 	array (see below) 	n/a
    @"primary-mime-type": ?[]u8 = null,

    // This torrent's queue position.
    // All torrents have a queue position, even if it's not queued.
    queuePosition: ?usize = null,

    //@"rateDownload (B/s)": ?usize = null,
    //@"rateUpload (B/s)": ?usize = null,

    // When `tr_stat.activity` is `TR_STATUS_CHECK` or `TR_STATUS_CHECK_WAIT`,
    // this is the percentage of how much of the files has been
    // verified. When it gets to 1, the verify process is done.
    // Range is [0..1]
    //  @see `tr_stat.activity`
    recheckProgress: ?f32 = null,

    // Number of seconds since the last activity (or since started).
    // -1 if activity is not seeding or downloading.
    secondsDownloading: ?f32 = null,

    // Cumulative seconds the torrent's ever spent seeding.
    secondsSeeding: ?f32 = null,

    //seedIdleLimit: ?usize = null,
    //seedIdleMode: ?usize = null,

    // ??
    seedRatioLimit: ?f32 = null,

    //seedRatioMode: ?usize = null,
    sequentialDownload: ?bool = null,

    // Byte count of all the piece data we'll have downloaded when we're done,
    // whether or not we have it yet. This may be less than `totalSize`
    // if only some of the torrent's files are wanted.
    sizeWhenDone: ?u64 = null,

    // When the torrent was last started.
    startDate: ?i64 = null,

    //status: ?usize = null,
    ////trackers 	array (see below) 	n/a
    trackerList: ?[]u8 = null,
    ////trackerStats 	array (see below) 	n/a
    //totalSize: ?usize = null,
    torrentFile: ?[]u8 = null,

    // Byte count of all data you've ever uploaded for this torrent.
    uploadedEver: ?u64 = null,

    //uploadLimit: ?usize = null,
    uploadLimited: ?bool = null,

    // ??
    uploadRatio: ?f32 = null,

    ////wanted 	array (see below) 	n/a

    // ??
    webseeds: ?[][]u8 = null,

    // Number of webseeds that are sending data to us.
    webseedsSendingToUs: ?u16 = null,
};

// Checks that all fields in Torrent are in sync with TorrentGet.Fields
test "torrent fields" {
    @setEvalBranchQuota(10000);

    const torrent_get_request_fields = comptime blk: {
        const kv = struct { []const u8 };
        var slice: []const kv = &[_]kv{};

        for (std.meta.fields(Request.TorrentGet.Fields)) |field| {
            slice = slice ++ &[_]kv{.{field.name}};
        }

        break :blk std.ComptimeStringMap(void, slice);
    };

    const torrent_fields = comptime blk: {
        const kv = struct { []const u8 };
        var slice: []const kv = &[_]kv{};

        for (std.meta.fields(Torrent)) |field| {
            slice = slice ++ &[_]kv{.{field.name}};
        }

        break :blk std.ComptimeStringMap(void, slice);
    };

    inline for (std.meta.fields(Torrent)) |field| {
        if (!torrent_get_request_fields.has(field.name)) {
            std.debug.print("field is present in Torrent but missing in TorrentGet: {s}\n", .{field.name});
        }
        //try std.testing.expect(torrent_get_request_fields.has(field.name));
    }

    inline for (std.meta.fields(Request.TorrentGet.Fields)) |field| {
        if (!torrent_fields.has(field.name)) {
            std.debug.print("field is present in TorrentGet but missing in Torrent: {s}\n", .{field.name});
        }
        //try std.testing.expect(torrent_fields.has(field.name));
    }
}