public API
This commit is contained in:
parent
984543fcb9
commit
ea3b22fccc
657
Cargo.lock
generated
657
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
|
@ -9,7 +9,7 @@ const EI: u64 = PI << 10;
|
|||
|
||||
#[derive(Debug, PartialEq, Copy, Clone, PartialOrd, Ord, Eq, Serialize, Deserialize, Default)]
|
||||
#[serde(transparent)]
|
||||
pub(crate) struct Bytes(pub(crate) u64);
|
||||
pub struct Bytes(pub(crate) u64);
|
||||
|
||||
impl Bytes {
|
||||
pub(crate) fn kib() -> Self {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::common::*;
|
||||
|
||||
pub(crate) struct Env {
|
||||
pub struct Env {
|
||||
args: Vec<OsString>,
|
||||
dir: PathBuf,
|
||||
input: Box<dyn InputStream>,
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::common::*;
|
|||
|
||||
#[derive(Debug, Snafu)]
|
||||
#[snafu(visibility(pub(crate)))]
|
||||
pub(crate) enum Error {
|
||||
pub enum Error {
|
||||
#[snafu(display("Failed to parse announce URL: {}", source))]
|
||||
AnnounceUrlParse { source: url::ParseError },
|
||||
#[snafu(display("Failed to parse byte count `{}`: {}", text, source))]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::common::*;
|
||||
|
||||
#[derive(Debug, PartialEq, Clone)]
|
||||
pub(crate) struct HostPort {
|
||||
pub struct HostPort {
|
||||
host: Host,
|
||||
port: u16,
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::common::*;
|
|||
|
||||
#[derive(Debug, Snafu)]
|
||||
#[snafu(visibility(pub(crate)))]
|
||||
pub(crate) enum HostPortParseError {
|
||||
pub enum HostPortParseError {
|
||||
#[snafu(display("Failed to parse host `{}`: {}", text, source))]
|
||||
Host {
|
||||
text: String,
|
||||
|
|
12
src/info.rs
12
src/info.rs
|
@ -1,22 +1,22 @@
|
|||
use crate::common::*;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
|
||||
pub(crate) struct Info {
|
||||
pub struct Info {
|
||||
#[serde(
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) private: Option<bool>,
|
||||
pub private: Option<bool>,
|
||||
#[serde(rename = "piece length")]
|
||||
pub(crate) piece_length: Bytes,
|
||||
pub(crate) name: String,
|
||||
pub piece_length: Bytes,
|
||||
pub name: String,
|
||||
#[serde(
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) source: Option<String>,
|
||||
pub source: Option<String>,
|
||||
pub(crate) pieces: PieceList,
|
||||
#[serde(flatten)]
|
||||
pub(crate) mode: Mode,
|
||||
|
@ -26,7 +26,7 @@ pub(crate) struct Info {
|
|||
with = "unwrap_or_skip",
|
||||
rename = "update-url"
|
||||
)]
|
||||
pub(crate) update_url: Option<Url>,
|
||||
pub update_url: Option<Url>,
|
||||
}
|
||||
|
||||
impl Info {
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::common::*;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||
pub(crate) struct Infohash {
|
||||
inner: Sha1Digest,
|
||||
pub struct Infohash {
|
||||
pub inner: Sha1Digest,
|
||||
}
|
||||
|
||||
impl Infohash {
|
||||
pub(crate) fn from_input(input: &Input) -> Result<Infohash, Error> {
|
||||
pub fn from_input(input: &Input) -> Result<Infohash, Error> {
|
||||
let value = Value::from_bencode(input.data()).map_err(|error| Error::MetainfoDecode {
|
||||
input: input.source().clone(),
|
||||
error,
|
||||
|
@ -43,7 +43,7 @@ impl Infohash {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn from_bencoded_info_dict(info: &[u8]) -> Infohash {
|
||||
pub fn from_bencoded_info_dict(info: &[u8]) -> Infohash {
|
||||
Infohash {
|
||||
inner: Sha1Digest::from_data(info),
|
||||
}
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
use crate::common::*;
|
||||
|
||||
pub(crate) struct Input {
|
||||
pub struct Input {
|
||||
source: InputTarget,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
|
||||
impl Input {
|
||||
pub(crate) fn new(source: InputTarget, data: Vec<u8>) -> Input {
|
||||
pub fn new(source: InputTarget, data: Vec<u8>) -> Input {
|
||||
Self { source, data }
|
||||
}
|
||||
|
||||
pub(crate) fn data(&self) -> &[u8] {
|
||||
pub fn data(&self) -> &[u8] {
|
||||
&self.data
|
||||
}
|
||||
|
||||
pub(crate) fn source(&self) -> &InputTarget {
|
||||
pub fn source(&self) -> &InputTarget {
|
||||
&self.source
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
use crate::common::*;
|
||||
|
||||
#[derive(PartialEq, Debug, Clone)]
|
||||
pub(crate) enum InputTarget {
|
||||
pub enum InputTarget {
|
||||
Path(PathBuf),
|
||||
Stdin,
|
||||
}
|
||||
|
||||
impl InputTarget {
|
||||
pub(crate) fn try_from_os_str(text: &OsStr) -> Result<Self, OsString> {
|
||||
pub fn try_from_os_str(text: &OsStr) -> Result<Self, OsString> {
|
||||
text
|
||||
.try_into()
|
||||
.map_err(|err: Error| OsString::from(err.to_string()))
|
||||
|
|
126
src/lib.rs
126
src/lib.rs
|
@ -41,85 +41,85 @@
|
|||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod assert_matches;
|
||||
pub mod assert_matches;
|
||||
|
||||
#[macro_use]
|
||||
mod errln;
|
||||
pub mod errln;
|
||||
|
||||
#[macro_use]
|
||||
mod err;
|
||||
pub mod err;
|
||||
|
||||
#[macro_use]
|
||||
mod out;
|
||||
pub mod out;
|
||||
|
||||
#[macro_use]
|
||||
mod outln;
|
||||
pub mod outln;
|
||||
|
||||
#[cfg(test)]
|
||||
#[macro_use]
|
||||
mod test_env;
|
||||
pub mod test_env;
|
||||
|
||||
#[cfg(test)]
|
||||
mod test_env_builder;
|
||||
pub mod test_env_builder;
|
||||
|
||||
#[cfg(test)]
|
||||
mod capture;
|
||||
pub mod capture;
|
||||
|
||||
mod arguments;
|
||||
mod bytes;
|
||||
mod common;
|
||||
mod consts;
|
||||
mod env;
|
||||
mod error;
|
||||
mod file_error;
|
||||
mod file_info;
|
||||
mod file_path;
|
||||
mod file_status;
|
||||
mod files;
|
||||
mod hasher;
|
||||
mod host_port;
|
||||
mod host_port_parse_error;
|
||||
mod info;
|
||||
mod infohash;
|
||||
mod input;
|
||||
mod input_stream;
|
||||
mod input_target;
|
||||
mod into_u64;
|
||||
mod into_usize;
|
||||
mod invariant;
|
||||
mod lint;
|
||||
mod linter;
|
||||
mod magnet_link;
|
||||
mod magnet_link_parse_error;
|
||||
mod md5_digest;
|
||||
mod metainfo;
|
||||
mod metainfo_error;
|
||||
mod mode;
|
||||
mod options;
|
||||
mod output_stream;
|
||||
mod output_target;
|
||||
mod piece_length_picker;
|
||||
mod piece_list;
|
||||
mod platform;
|
||||
mod platform_interface;
|
||||
mod print;
|
||||
mod reckoner;
|
||||
mod run;
|
||||
mod sha1_digest;
|
||||
mod shell;
|
||||
mod sort_key;
|
||||
mod sort_order;
|
||||
mod sort_spec;
|
||||
mod status;
|
||||
mod step;
|
||||
mod style;
|
||||
mod subcommand;
|
||||
mod table;
|
||||
mod torrent_summary;
|
||||
mod use_color;
|
||||
mod verifier;
|
||||
mod walker;
|
||||
mod xor_args;
|
||||
pub mod arguments;
|
||||
pub mod bytes;
|
||||
pub mod common;
|
||||
pub mod consts;
|
||||
pub mod env;
|
||||
pub mod error;
|
||||
pub mod file_error;
|
||||
pub mod file_info;
|
||||
pub mod file_path;
|
||||
pub mod file_status;
|
||||
pub mod files;
|
||||
pub mod hasher;
|
||||
pub mod host_port;
|
||||
pub mod host_port_parse_error;
|
||||
pub mod info;
|
||||
pub mod infohash;
|
||||
pub mod input;
|
||||
pub mod input_stream;
|
||||
pub mod input_target;
|
||||
pub mod into_u64;
|
||||
pub mod into_usize;
|
||||
pub mod invariant;
|
||||
pub mod lint;
|
||||
pub mod linter;
|
||||
pub mod magnet_link;
|
||||
pub mod magnet_link_parse_error;
|
||||
pub mod md5_digest;
|
||||
pub mod metainfo;
|
||||
pub mod metainfo_error;
|
||||
pub mod mode;
|
||||
pub mod options;
|
||||
pub mod output_stream;
|
||||
pub mod output_target;
|
||||
pub mod piece_length_picker;
|
||||
pub mod piece_list;
|
||||
pub mod platform;
|
||||
pub mod platform_interface;
|
||||
pub mod print;
|
||||
pub mod reckoner;
|
||||
pub mod run;
|
||||
pub mod sha1_digest;
|
||||
pub mod shell;
|
||||
pub mod sort_key;
|
||||
pub mod sort_order;
|
||||
pub mod sort_spec;
|
||||
pub mod status;
|
||||
pub mod step;
|
||||
pub mod style;
|
||||
pub mod subcommand;
|
||||
pub mod table;
|
||||
pub mod torrent_summary;
|
||||
pub mod use_color;
|
||||
pub mod verifier;
|
||||
pub mod walker;
|
||||
pub mod xor_args;
|
||||
|
||||
#[cfg(feature = "bench")]
|
||||
pub mod bench;
|
||||
|
|
|
@ -1,17 +1,17 @@
|
|||
use crate::common::*;
|
||||
|
||||
#[derive(Debug, PartialEq)]
|
||||
pub(crate) struct MagnetLink {
|
||||
infohash: Infohash,
|
||||
name: Option<String>,
|
||||
peers: Vec<HostPort>,
|
||||
trackers: Vec<Url>,
|
||||
indices: BTreeSet<u64>,
|
||||
pub struct MagnetLink {
|
||||
pub infohash: Infohash,
|
||||
pub name: Option<String>,
|
||||
pub peers: Vec<HostPort>,
|
||||
pub trackers: Vec<Url>,
|
||||
pub indices: BTreeSet<u64>,
|
||||
}
|
||||
|
||||
impl MagnetLink {
|
||||
/// See `Info::infohash_lossy` for details on when this function is lossy.
|
||||
pub(crate) fn from_metainfo_lossy(metainfo: &Metainfo) -> Result<MagnetLink> {
|
||||
pub fn from_metainfo_lossy(metainfo: &Metainfo) -> Result<MagnetLink> {
|
||||
let mut link = Self::with_infohash(metainfo.infohash_lossy()?);
|
||||
|
||||
link.set_name(metainfo.info.name.clone());
|
||||
|
@ -23,7 +23,7 @@ impl MagnetLink {
|
|||
Ok(link)
|
||||
}
|
||||
|
||||
pub(crate) fn with_infohash(infohash: Infohash) -> Self {
|
||||
pub fn with_infohash(infohash: Infohash) -> Self {
|
||||
MagnetLink {
|
||||
infohash,
|
||||
name: None,
|
||||
|
@ -34,23 +34,23 @@ impl MagnetLink {
|
|||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn set_name(&mut self, name: impl Into<String>) {
|
||||
pub fn set_name(&mut self, name: impl Into<String>) {
|
||||
self.name = Some(name.into());
|
||||
}
|
||||
|
||||
pub(crate) fn add_peer(&mut self, peer: HostPort) {
|
||||
pub fn add_peer(&mut self, peer: HostPort) {
|
||||
self.peers.push(peer);
|
||||
}
|
||||
|
||||
pub(crate) fn add_tracker(&mut self, tracker: Url) {
|
||||
pub fn add_tracker(&mut self, tracker: Url) {
|
||||
self.trackers.push(tracker);
|
||||
}
|
||||
|
||||
pub(crate) fn add_index(&mut self, index: u64) {
|
||||
pub fn add_index(&mut self, index: u64) {
|
||||
self.indices.insert(index);
|
||||
}
|
||||
|
||||
pub(crate) fn to_url(&self) -> Url {
|
||||
pub fn to_url(&self) -> Url {
|
||||
let mut url = Url::parse("magnet:").invariant_unwrap("`magnet:` is valid URL");
|
||||
|
||||
let mut query = format!("xt=urn:btih:{}", self.infohash);
|
||||
|
@ -85,7 +85,7 @@ impl MagnetLink {
|
|||
url
|
||||
}
|
||||
|
||||
fn parse(text: &str) -> Result<Self, MagnetLinkParseError> {
|
||||
pub fn parse(text: &str) -> Result<Self, MagnetLinkParseError> {
|
||||
let url = Url::parse(&text).context(magnet_link_parse_error::Url)?;
|
||||
|
||||
if url.scheme() != "magnet" {
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::common::*;
|
|||
|
||||
#[derive(Debug, Snafu)]
|
||||
#[snafu(visibility(pub(crate)))]
|
||||
pub(crate) enum MagnetLinkParseError {
|
||||
pub enum MagnetLinkParseError {
|
||||
#[snafu(display("Failed to parse hex string `{}`: {}", text, source))]
|
||||
HexParse {
|
||||
text: String,
|
||||
|
|
|
@ -1,68 +1,68 @@
|
|||
use crate::common::*;
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, PartialEq, Clone)]
|
||||
pub(crate) struct Metainfo {
|
||||
pub struct Metainfo {
|
||||
#[serde(
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) announce: Option<String>,
|
||||
pub announce: Option<String>,
|
||||
#[serde(
|
||||
rename = "announce-list",
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) announce_list: Option<Vec<Vec<String>>>,
|
||||
pub announce_list: Option<Vec<Vec<String>>>,
|
||||
#[serde(
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) comment: Option<String>,
|
||||
pub comment: Option<String>,
|
||||
#[serde(
|
||||
rename = "created by",
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) created_by: Option<String>,
|
||||
pub created_by: Option<String>,
|
||||
#[serde(
|
||||
rename = "creation date",
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) creation_date: Option<u64>,
|
||||
pub creation_date: Option<u64>,
|
||||
#[serde(
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) encoding: Option<String>,
|
||||
pub(crate) info: Info,
|
||||
pub encoding: Option<String>,
|
||||
pub info: Info,
|
||||
#[serde(
|
||||
skip_serializing_if = "Option::is_none",
|
||||
default,
|
||||
with = "unwrap_or_skip"
|
||||
)]
|
||||
pub(crate) nodes: Option<Vec<HostPort>>,
|
||||
pub nodes: Option<Vec<HostPort>>,
|
||||
}
|
||||
|
||||
impl Metainfo {
|
||||
pub(crate) fn from_input(input: &Input) -> Result<Metainfo> {
|
||||
pub fn from_input(input: &Input) -> Result<Metainfo> {
|
||||
Self::deserialize(input.source(), input.data())
|
||||
}
|
||||
|
||||
pub(crate) fn deserialize(source: &InputTarget, data: &[u8]) -> Result<Metainfo, Error> {
|
||||
pub fn deserialize(source: &InputTarget, data: &[u8]) -> Result<Metainfo, Error> {
|
||||
let metainfo = bendy::serde::de::from_bytes(&data).context(error::MetainfoDeserialize {
|
||||
input: source.clone(),
|
||||
})?;
|
||||
Ok(metainfo)
|
||||
}
|
||||
|
||||
pub(crate) fn serialize(&self) -> Result<Vec<u8>, Error> {
|
||||
pub fn serialize(&self) -> Result<Vec<u8>, Error> {
|
||||
bendy::serde::ser::to_bytes(&self).context(error::MetainfoSerialize)
|
||||
}
|
||||
|
||||
|
@ -99,7 +99,7 @@ impl Metainfo {
|
|||
self.info.content_size()
|
||||
}
|
||||
|
||||
pub(crate) fn trackers<'a>(&'a self) -> impl Iterator<Item = Result<Url>> + 'a {
|
||||
pub fn trackers<'a>(&'a self) -> impl Iterator<Item = Result<Url>> + 'a {
|
||||
let mut seen = HashSet::new();
|
||||
iter::once(&self.announce)
|
||||
.flatten()
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::common::*;
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
pub(crate) enum MetainfoError {
|
||||
pub enum MetainfoError {
|
||||
Type,
|
||||
InfoMissing,
|
||||
InfoType,
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
use crate::common::*;
|
||||
|
||||
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
|
||||
pub(crate) struct Sha1Digest {
|
||||
bytes: [u8; Self::LENGTH],
|
||||
pub struct Sha1Digest {
|
||||
pub bytes: [u8; Self::LENGTH],
|
||||
}
|
||||
|
||||
impl Sha1Digest {
|
||||
pub(crate) const LENGTH: usize = 20;
|
||||
pub const LENGTH: usize = 20;
|
||||
|
||||
pub(crate) fn from_bytes(bytes: [u8; Self::LENGTH]) -> Self {
|
||||
pub fn from_bytes(bytes: [u8; Self::LENGTH]) -> Self {
|
||||
Sha1Digest { bytes }
|
||||
}
|
||||
|
||||
pub(crate) fn bytes(self) -> [u8; Self::LENGTH] {
|
||||
pub fn bytes(self) -> [u8; Self::LENGTH] {
|
||||
self.bytes
|
||||
}
|
||||
|
||||
pub(crate) fn from_data(data: impl AsRef<[u8]>) -> Self {
|
||||
pub fn from_data(data: impl AsRef<[u8]>) -> Self {
|
||||
Sha1::from(data).digest().into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use structopt::clap;
|
|||
|
||||
#[derive(Copy, Clone, EnumVariantNames, IntoStaticStr, EnumString, EnumIter, Debug)]
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
pub(crate) enum Shell {
|
||||
pub enum Shell {
|
||||
Zsh,
|
||||
Bash,
|
||||
Fish,
|
||||
|
|
|
@ -1,30 +1,30 @@
|
|||
use crate::common::*;
|
||||
|
||||
pub(crate) struct TorrentSummary {
|
||||
pub struct TorrentSummary {
|
||||
infohash: Infohash,
|
||||
metainfo: Metainfo,
|
||||
size: Bytes,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub(crate) struct TorrentSummaryJson {
|
||||
name: String,
|
||||
comment: Option<String>,
|
||||
creation_date: Option<u64>,
|
||||
created_by: Option<String>,
|
||||
source: Option<String>,
|
||||
info_hash: String,
|
||||
torrent_size: u64,
|
||||
content_size: u64,
|
||||
private: bool,
|
||||
tracker: Option<String>,
|
||||
announce_list: Vec<Vec<String>>,
|
||||
update_url: Option<String>,
|
||||
dht_nodes: Vec<String>,
|
||||
piece_size: u64,
|
||||
piece_count: usize,
|
||||
file_count: usize,
|
||||
files: Vec<String>,
|
||||
pub struct TorrentSummaryJson {
|
||||
pub name: String,
|
||||
pub comment: Option<String>,
|
||||
pub creation_date: Option<u64>,
|
||||
pub created_by: Option<String>,
|
||||
pub source: Option<String>,
|
||||
pub info_hash: String,
|
||||
pub torrent_size: u64,
|
||||
pub content_size: u64,
|
||||
pub private: bool,
|
||||
pub tracker: Option<String>,
|
||||
pub announce_list: Vec<Vec<String>>,
|
||||
pub update_url: Option<String>,
|
||||
pub dht_nodes: Vec<String>,
|
||||
pub piece_size: u64,
|
||||
pub piece_count: usize,
|
||||
pub file_count: usize,
|
||||
pub files: Vec<String>,
|
||||
}
|
||||
|
||||
impl TorrentSummary {
|
||||
|
@ -37,14 +37,14 @@ impl TorrentSummary {
|
|||
}
|
||||
|
||||
/// See `Info::infohash_lossy` for details on when this function is lossy.
|
||||
pub(crate) fn from_metainfo_lossy(metainfo: Metainfo) -> Result<Self> {
|
||||
pub fn from_metainfo_lossy(metainfo: Metainfo) -> Result<Self> {
|
||||
let bytes = metainfo.serialize()?;
|
||||
let size = Bytes(bytes.len().into_u64());
|
||||
let infohash = metainfo.infohash_lossy()?;
|
||||
Ok(Self::new(metainfo, infohash, size))
|
||||
}
|
||||
|
||||
pub(crate) fn from_input(input: &Input) -> Result<Self> {
|
||||
pub fn from_input(input: &Input) -> Result<Self> {
|
||||
let metainfo = Metainfo::from_input(input)?;
|
||||
let infohash = Infohash::from_input(input)?;
|
||||
let size = Bytes(input.data().len().into_u64());
|
||||
|
@ -52,7 +52,7 @@ impl TorrentSummary {
|
|||
Ok(Self::new(metainfo, infohash, size))
|
||||
}
|
||||
|
||||
pub(crate) fn write(&self, env: &mut Env) -> Result<()> {
|
||||
pub fn write(&self, env: &mut Env) -> Result<()> {
|
||||
let table = self.table();
|
||||
|
||||
if env.out().is_term() {
|
||||
|
@ -168,14 +168,14 @@ impl TorrentSummary {
|
|||
table
|
||||
}
|
||||
|
||||
pub(crate) fn write_json(&self, env: &mut Env) -> Result<()> {
|
||||
pub fn write_json(&self, env: &mut Env) -> Result<()> {
|
||||
let data = self.torrent_summary_data();
|
||||
let json = serde_json::to_string(&data).context(error::JsonSerialize)?;
|
||||
outln!(env, "{}", json)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn torrent_summary_data(&self) -> TorrentSummaryJson {
|
||||
pub fn torrent_summary_data(&self) -> TorrentSummaryJson {
|
||||
let (file_count, files) = match &self.metainfo.info.mode {
|
||||
Mode::Single { .. } => (1, vec![self.metainfo.info.name.clone()]),
|
||||
Mode::Multiple { files } => (
|
||||
|
|
Loading…
Reference in New Issue
Block a user