From 66d56d7a2b64c5ed13860d809d9bf35d86292df2 Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Thu, 10 Jul 2025 15:50:16 +0200 Subject: refactor(crates/bytes): Move into yt `yt_dlp` no longer depends on it. --- crates/bytes/.gitignore | 11 -- crates/bytes/Cargo.lock | 65 --------- crates/bytes/Cargo.lock.license | 9 -- crates/bytes/Cargo.toml | 33 ----- crates/bytes/src/error.rs | 39 ------ crates/bytes/src/lib.rs | 249 --------------------------------- crates/bytes/src/serde.rs | 19 --- crates/bytes/update.sh | 15 -- crates/yt/Cargo.toml | 1 - crates/yt/src/main.rs | 7 +- crates/yt/src/shared/bytes/error.rs | 39 ++++++ crates/yt/src/shared/bytes/mod.rs | 265 ++++++++++++++++++++++++++++++++++++ crates/yt/src/shared/mod.rs | 1 + 13 files changed, 310 insertions(+), 443 deletions(-) delete mode 100644 crates/bytes/.gitignore delete mode 100644 crates/bytes/Cargo.lock delete mode 100644 crates/bytes/Cargo.lock.license delete mode 100644 crates/bytes/Cargo.toml delete mode 100644 crates/bytes/src/error.rs delete mode 100644 crates/bytes/src/lib.rs delete mode 100644 crates/bytes/src/serde.rs delete mode 100755 crates/bytes/update.sh create mode 100644 crates/yt/src/shared/bytes/error.rs create mode 100644 crates/yt/src/shared/bytes/mod.rs create mode 100644 crates/yt/src/shared/mod.rs diff --git a/crates/bytes/.gitignore b/crates/bytes/.gitignore deleted file mode 100644 index 8876ea6..0000000 --- a/crates/bytes/.gitignore +++ /dev/null @@ -1,11 +0,0 @@ -# yt - A fully featured command line YouTube client -# -# Copyright (C) 2024 Benedikt Peetz -# SPDX-License-Identifier: GPL-3.0-or-later -# -# This file is part of Yt. -# -# You should have received a copy of the License along with this program. -# If not, see . - -/target diff --git a/crates/bytes/Cargo.lock b/crates/bytes/Cargo.lock deleted file mode 100644 index b30ba3d..0000000 --- a/crates/bytes/Cargo.lock +++ /dev/null @@ -1,65 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 3 - -[[package]] -name = "bytes" -version = "1.0.0" -dependencies = [ - "serde", -] - -[[package]] -name = "proc-macro2" -version = "1.0.86" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.37" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "serde" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.210" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "syn" -version = "2.0.77" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "unicode-ident" -version = "1.0.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" diff --git a/crates/bytes/Cargo.lock.license b/crates/bytes/Cargo.lock.license deleted file mode 100644 index d4d410f..0000000 --- a/crates/bytes/Cargo.lock.license +++ /dev/null @@ -1,9 +0,0 @@ -yt - A fully featured command line YouTube client - -Copyright (C) 2024 Benedikt Peetz -SPDX-License-Identifier: GPL-3.0-or-later - -This file is part of Yt. - -You should have received a copy of the License along with this program. -If not, see . diff --git a/crates/bytes/Cargo.toml b/crates/bytes/Cargo.toml deleted file mode 100644 index 4439aa8..0000000 --- a/crates/bytes/Cargo.toml +++ /dev/null @@ -1,33 +0,0 @@ -# yt - A fully featured command line YouTube client -# -# Copyright (C) 2024 Benedikt Peetz -# SPDX-License-Identifier: GPL-3.0-or-later -# -# This file is part of Yt. -# -# You should have received a copy of the License along with this program. -# If not, see . - -[package] -name = "bytes" -description = "Simple byte formatting utilities" -keywords = [] -categories = [] -version.workspace = true -edition.workspace = true -authors.workspace = true -license.workspace = true -repository.workspace = true -rust-version.workspace = true -publish = false - -[dependencies] -serde.workspace = true - -[dev-dependencies] - -[lints] -workspace = true - -[package.metadata.docs.rs] -all-features = true diff --git a/crates/bytes/src/error.rs b/crates/bytes/src/error.rs deleted file mode 100644 index c9783d8..0000000 --- a/crates/bytes/src/error.rs +++ /dev/null @@ -1,39 +0,0 @@ -// yt - A fully featured command line YouTube client -// -// Copyright (C) 2024 Benedikt Peetz -// SPDX-License-Identifier: GPL-3.0-or-later -// -// This file is part of Yt. -// -// You should have received a copy of the License along with this program. -// If not, see . - -use std::{fmt::Display, num::ParseIntError}; - -#[derive(Debug)] -#[allow(clippy::module_name_repetitions)] -pub enum BytesError { - BytesParseIntError(ParseIntError), - NotYetSupported(String), -} - -impl Display for BytesError { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - BytesError::BytesParseIntError(e) => { - f.write_fmt(format_args!("Failed to parse a number as integer: '{e}'")) - }, - BytesError::NotYetSupported(other) => { - f.write_fmt(format_args!("Your extension '{other}' is not yet supported. Only KB,MB,GB or KiB,MiB,GiB are supported")) - } - } - } -} - -impl From for BytesError { - fn from(value: ParseIntError) -> Self { - Self::BytesParseIntError(value) - } -} - -impl std::error::Error for BytesError {} diff --git a/crates/bytes/src/lib.rs b/crates/bytes/src/lib.rs deleted file mode 100644 index 2a9248d..0000000 --- a/crates/bytes/src/lib.rs +++ /dev/null @@ -1,249 +0,0 @@ -// yt - A fully featured command line YouTube client -// -// Copyright (C) 2024 Benedikt Peetz -// SPDX-License-Identifier: GPL-3.0-or-later -// -// This file is part of Yt. -// -// You should have received a copy of the License along with this program. -// If not, see . - -#![allow( - clippy::cast_possible_truncation, - clippy::cast_precision_loss, - clippy::cast_sign_loss, - clippy::cast_possible_wrap -)] -use std::{fmt::Display, str::FromStr}; - -use error::BytesError; - -const B: u64 = 1; - -const KIB: u64 = 1024 * B; -const MIB: u64 = 1024 * KIB; -const GIB: u64 = 1024 * MIB; -const TIB: u64 = 1024 * GIB; -const PIB: u64 = 1024 * TIB; - -const KB: u64 = 1000 * B; -const MB: u64 = 1000 * KB; -const GB: u64 = 1000 * MB; -const TB: u64 = 1000 * GB; - -pub mod error; -pub mod serde; - -#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq)] -pub struct Bytes(u64); - -impl Bytes { - #[must_use] - pub fn as_u64(self) -> u64 { - self.0 - } - #[must_use] - pub fn new(v: u64) -> Self { - Self(v) - } -} - -impl FromStr for Bytes { - type Err = BytesError; - - fn from_str(s: &str) -> Result { - let s = s.chars().filter(|s| !s.is_whitespace()).collect::(); - - let (whole_number, s): (u64, &str) = { - let number = s.chars().take_while(|x| x.is_numeric()).collect::(); - - (number.parse()?, &s[number.len()..]) - }; - - let (decimal_number, s, raise_factor) = { - if s.starts_with('.') { - let s_str = s - .chars() - .skip(1) // the decimal point - .take_while(|x| x.is_numeric()) - .collect::(); - - let s_num = s_str.parse::()?; - - (s_num, &s[s_str.len()..], s_str.len() as u32) - } else { - (0u64, s, 0) - } - }; - - let number = (whole_number * (10u64.pow(raise_factor))) + decimal_number; - - let extension = s.chars().skip_while(|x| x.is_numeric()).collect::(); - - let output = match extension.to_lowercase().as_str() { - "" => number, - "b" => number * B, - "kib" => number * KIB, - "mib" => number * MIB, - "gib" => number * GIB, - "tib" => number * TIB, - "kb" => number * KB, - "mb" => number * MB, - "gb" => number * GB, - "tb" => number * TB, - other => return Err(BytesError::NotYetSupported(other.to_owned())), - }; - - Ok(Self(output / (10u64.pow(raise_factor)))) - } -} - -impl Display for Bytes { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let num = self.0; - - match num { - 0..KIB => f.write_fmt(format_args!("{} {}", num, "B"))?, - KIB..MIB => f.write_fmt(format_args!( - "{} {}", - precision_f64((num as f64) / (KIB as f64), 3), - "KiB" - ))?, - MIB..GIB => f.write_fmt(format_args!( - "{} {}", - precision_f64((num as f64) / (MIB as f64), 3), - "MiB" - ))?, - GIB..TIB => f.write_fmt(format_args!( - "{} {}", - precision_f64((num as f64) / (GIB as f64), 3), - "GiB" - ))?, - TIB..PIB => f.write_fmt(format_args!( - "{} {}", - precision_f64((num as f64) / (TIB as f64), 3), - "TiB" - ))?, - PIB.. => todo!(), - } - - Ok(()) - } -} - -// taken from this stack overflow question: https://stackoverflow.com/a/76572321 -/// Round to significant digits (rather than digits after the decimal). -/// -/// Not implemented for `f32`, because such an implementation showed precision -/// glitches (e.g. `precision_f32(12300.0, 2) == 11999.999`), so for `f32` -/// floats, convert to `f64` for this function and back as needed. -/// -/// Examples: -/// ``` -///# fn main() { -///# use bytes::precision_f64; -/// assert_eq!(precision_f64(1.2300, 2), 1.2f64); -/// assert_eq!(precision_f64(1.2300_f64, 2), 1.2f64); -/// assert_eq!(precision_f64(1.2300_f32 as f64, 2), 1.2f64); -/// assert_eq!(precision_f64(1.2300_f32 as f64, 2) as f32, 1.2f32); -///# } -/// ``` -#[must_use] -pub fn precision_f64(x: f64, decimals: u32) -> f64 { - if x == 0. || decimals == 0 { - 0. - } else { - let shift = decimals as i32 - x.abs().log10().ceil() as i32; - let shift_factor = 10_f64.powi(shift); - - (x * shift_factor).round() / shift_factor - } -} - -#[cfg(test)] -mod tests { - use super::{Bytes, GIB}; - - #[test] - fn parsing() { - let input: Bytes = "20 GiB".parse().unwrap(); - let expected = 20 * GIB; - - assert_eq!(expected, input.0); - } - #[test] - fn parsing_not_round() { - let input: Bytes = "2.34 GiB".parse().unwrap(); - let expected = "2.34 GiB"; - - assert_eq!(expected, input.to_string().as_str()); - } - - #[test] - fn round_trip_1kib() { - let input = "1 KiB"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!(input.to_owned(), parsed.to_string()); - } - #[test] - fn round_trip_2kib() { - let input = "2 KiB"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!(input.to_owned(), parsed.to_string()); - } - - #[test] - fn round_trip_1mib() { - let input = "1 MiB"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!(input.to_owned(), parsed.to_string()); - } - #[test] - fn round_trip_2mib() { - let input = "2 MiB"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!(input.to_owned(), parsed.to_string()); - } - - #[test] - fn round_trip_1gib() { - let input = "1 GiB"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!(input.to_owned(), parsed.to_string()); - } - #[test] - fn round_trip_2gib() { - let input = "2 GiB"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!(input.to_owned(), parsed.to_string()); - } - - #[test] - fn round_trip() { - let input = "20 TiB"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!(input.to_owned(), parsed.to_string()); - } - - #[test] - fn round_trip_decmimal() { - let input = "20 TB"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!("18.2 TiB", parsed.to_string()); - } - #[test] - fn round_trip_1b() { - let input = "1"; - let parsed: Bytes = input.parse().unwrap(); - - assert_eq!("1 B", parsed.to_string()); - } -} diff --git a/crates/bytes/src/serde.rs b/crates/bytes/src/serde.rs deleted file mode 100644 index 4341e32..0000000 --- a/crates/bytes/src/serde.rs +++ /dev/null @@ -1,19 +0,0 @@ -// yt - A fully featured command line YouTube client -// -// Copyright (C) 2024 Benedikt Peetz -// SPDX-License-Identifier: GPL-3.0-or-later -// -// This file is part of Yt. -// -// You should have received a copy of the License along with this program. -// If not, see . - -use serde::{Serialize, Serializer}; - -use crate::Bytes; - -impl Serialize for Bytes { - fn serialize(&self, serializer: S) -> Result { - serializer.serialize_str(self.to_string().as_str()) - } -} diff --git a/crates/bytes/update.sh b/crates/bytes/update.sh deleted file mode 100755 index c1a0215..0000000 --- a/crates/bytes/update.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/env sh - -# yt - A fully featured command line YouTube client -# -# Copyright (C) 2024 Benedikt Peetz -# SPDX-License-Identifier: GPL-3.0-or-later -# -# This file is part of Yt. -# -# You should have received a copy of the License along with this program. -# If not, see . - -cd "$(dirname "$0")" || exit 1 -[ "$1" = "upgrade" ] && cargo upgrade --incompatible -cargo update diff --git a/crates/yt/Cargo.toml b/crates/yt/Cargo.toml index c3ed3b0..0a9227f 100644 --- a/crates/yt/Cargo.toml +++ b/crates/yt/Cargo.toml @@ -39,7 +39,6 @@ tempfile = "3.20.0" toml = "0.8.23" xdg = "3.0.0" shlex = "1.3.0" -bytes.workspace = true libmpv2.workspace = true log.workspace = true serde.workspace = true diff --git a/crates/yt/src/main.rs b/crates/yt/src/main.rs index f78c23e..f6f18be 100644 --- a/crates/yt/src/main.rs +++ b/crates/yt/src/main.rs @@ -17,7 +17,6 @@ use std::{env::current_exe, sync::Arc}; use anyhow::{Context, Result, bail}; use app::App; -use bytes::Bytes; use cache::{invalidate, maintain}; use clap::{CommandFactory, Parser}; use cli::{CacheCommand, SelectCommand, SubscriptionCommand, VideosCommand}; @@ -31,7 +30,11 @@ use tokio::{ task::JoinHandle, }; -use crate::{cli::Command, storage::subscriptions}; +use crate::{ + cli::Command, + shared::bytes::Bytes, + storage::subscription, +}; pub mod ansi_escape_codes; pub mod app; diff --git a/crates/yt/src/shared/bytes/error.rs b/crates/yt/src/shared/bytes/error.rs new file mode 100644 index 0000000..c9783d8 --- /dev/null +++ b/crates/yt/src/shared/bytes/error.rs @@ -0,0 +1,39 @@ +// yt - A fully featured command line YouTube client +// +// Copyright (C) 2024 Benedikt Peetz +// SPDX-License-Identifier: GPL-3.0-or-later +// +// This file is part of Yt. +// +// You should have received a copy of the License along with this program. +// If not, see . + +use std::{fmt::Display, num::ParseIntError}; + +#[derive(Debug)] +#[allow(clippy::module_name_repetitions)] +pub enum BytesError { + BytesParseIntError(ParseIntError), + NotYetSupported(String), +} + +impl Display for BytesError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BytesError::BytesParseIntError(e) => { + f.write_fmt(format_args!("Failed to parse a number as integer: '{e}'")) + }, + BytesError::NotYetSupported(other) => { + f.write_fmt(format_args!("Your extension '{other}' is not yet supported. Only KB,MB,GB or KiB,MiB,GiB are supported")) + } + } + } +} + +impl From for BytesError { + fn from(value: ParseIntError) -> Self { + Self::BytesParseIntError(value) + } +} + +impl std::error::Error for BytesError {} diff --git a/crates/yt/src/shared/bytes/mod.rs b/crates/yt/src/shared/bytes/mod.rs new file mode 100644 index 0000000..31e782e --- /dev/null +++ b/crates/yt/src/shared/bytes/mod.rs @@ -0,0 +1,265 @@ +// yt - A fully featured command line YouTube client +// +// Copyright (C) 2024 Benedikt Peetz +// SPDX-License-Identifier: GPL-3.0-or-later +// +// This file is part of Yt. +// +// You should have received a copy of the License along with this program. +// If not, see . + +#![allow( + clippy::cast_possible_truncation, + clippy::cast_precision_loss, + clippy::cast_sign_loss, + clippy::cast_possible_wrap +)] +use std::{fmt::Display, str::FromStr}; + +use ::serde::{Deserialize, Serialize}; +use error::BytesError; + +const B: u64 = 1; + +const KIB: u64 = 1024 * B; +const MIB: u64 = 1024 * KIB; +const GIB: u64 = 1024 * MIB; +const TIB: u64 = 1024 * GIB; +const PIB: u64 = 1024 * TIB; + +const KB: u64 = 1000 * B; +const MB: u64 = 1000 * KB; +const GB: u64 = 1000 * MB; +const TB: u64 = 1000 * GB; + +pub(crate) mod error; + +#[derive(Clone, Copy, Debug, PartialEq, PartialOrd, Ord, Eq, Deserialize, Serialize)] +#[serde(try_from = "String")] +#[serde(into = "String")] +pub struct Bytes(u64); + +impl Bytes { + #[must_use] + pub fn as_u64(self) -> u64 { + self.0 + } + #[must_use] + pub fn new(v: u64) -> Self { + Self(v) + } +} + +impl FromStr for Bytes { + type Err = BytesError; + + fn from_str(s: &str) -> Result { + let s = s.chars().filter(|s| !s.is_whitespace()).collect::(); + + let (whole_number, s): (u64, &str) = { + let number = s.chars().take_while(|x| x.is_numeric()).collect::(); + + (number.parse()?, &s[number.len()..]) + }; + + let (decimal_number, s, raise_factor) = { + if s.starts_with('.') { + let s_str = s + .chars() + .skip(1) // the decimal point + .take_while(|x| x.is_numeric()) + .collect::(); + + let s_num = s_str.parse::()?; + + (s_num, &s[s_str.len()..], s_str.len() as u32) + } else { + (0u64, s, 0) + } + }; + + let number = (whole_number * (10u64.pow(raise_factor))) + decimal_number; + + let extension = s.chars().skip_while(|x| x.is_numeric()).collect::(); + + let output = match extension.to_lowercase().as_str() { + "" => number, + "b" => number * B, + "kib" => number * KIB, + "mib" => number * MIB, + "gib" => number * GIB, + "tib" => number * TIB, + "kb" => number * KB, + "mb" => number * MB, + "gb" => number * GB, + "tb" => number * TB, + other => return Err(BytesError::NotYetSupported(other.to_owned())), + }; + + Ok(Self(output / (10u64.pow(raise_factor)))) + } +} + +impl Display for Bytes { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let num = self.0; + + match num { + 0..KIB => f.write_fmt(format_args!("{} {}", num, "B"))?, + KIB..MIB => f.write_fmt(format_args!( + "{} {}", + precision_f64((num as f64) / (KIB as f64), 3), + "KiB" + ))?, + MIB..GIB => f.write_fmt(format_args!( + "{} {}", + precision_f64((num as f64) / (MIB as f64), 3), + "MiB" + ))?, + GIB..TIB => f.write_fmt(format_args!( + "{} {}", + precision_f64((num as f64) / (GIB as f64), 3), + "GiB" + ))?, + TIB..PIB => f.write_fmt(format_args!( + "{} {}", + precision_f64((num as f64) / (TIB as f64), 3), + "TiB" + ))?, + PIB.. => todo!(), + } + + Ok(()) + } +} + +impl From for String { + fn from(value: Bytes) -> Self { + value.to_string() + } +} + +impl TryFrom for Bytes { + type Error = BytesError; + + fn try_from(value: String) -> Result { + value.as_str().parse() + } +} + +// taken from this stack overflow question: https://stackoverflow.com/a/76572321 +/// Round to significant digits (rather than digits after the decimal). +/// +/// Not implemented for `f32`, because such an implementation showed precision +/// glitches (e.g. `precision_f32(12300.0, 2) == 11999.999`), so for `f32` +/// floats, convert to `f64` for this function and back as needed. +/// +/// Examples: +/// ``` +///# fn main() { +///# use bytes::precision_f64; +/// assert_eq!(precision_f64(1.2300, 2), 1.2f64); +/// assert_eq!(precision_f64(1.2300_f64, 2), 1.2f64); +/// assert_eq!(precision_f64(1.2300_f32 as f64, 2), 1.2f64); +/// assert_eq!(precision_f64(1.2300_f32 as f64, 2) as f32, 1.2f32); +///# } +/// ``` +#[must_use] +pub(crate) fn precision_f64(x: f64, decimals: u32) -> f64 { + if x == 0. || decimals == 0 { + 0. + } else { + let shift = decimals as i32 - x.abs().log10().ceil() as i32; + let shift_factor = 10_f64.powi(shift); + + (x * shift_factor).round() / shift_factor + } +} + +#[cfg(test)] +mod tests { + use super::{Bytes, GIB}; + + #[test] + fn parsing() { + let input: Bytes = "20 GiB".parse().unwrap(); + let expected = 20 * GIB; + + assert_eq!(expected, input.0); + } + #[test] + fn parsing_not_round() { + let input: Bytes = "2.34 GiB".parse().unwrap(); + let expected = "2.34 GiB"; + + assert_eq!(expected, input.to_string().as_str()); + } + + #[test] + fn round_trip_1kib() { + let input = "1 KiB"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!(input.to_owned(), parsed.to_string()); + } + #[test] + fn round_trip_2kib() { + let input = "2 KiB"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!(input.to_owned(), parsed.to_string()); + } + + #[test] + fn round_trip_1mib() { + let input = "1 MiB"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!(input.to_owned(), parsed.to_string()); + } + #[test] + fn round_trip_2mib() { + let input = "2 MiB"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!(input.to_owned(), parsed.to_string()); + } + + #[test] + fn round_trip_1gib() { + let input = "1 GiB"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!(input.to_owned(), parsed.to_string()); + } + #[test] + fn round_trip_2gib() { + let input = "2 GiB"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!(input.to_owned(), parsed.to_string()); + } + + #[test] + fn round_trip() { + let input = "20 TiB"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!(input.to_owned(), parsed.to_string()); + } + + #[test] + fn round_trip_decmimal() { + let input = "20 TB"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!("18.2 TiB", parsed.to_string()); + } + #[test] + fn round_trip_1b() { + let input = "1"; + let parsed: Bytes = input.parse().unwrap(); + + assert_eq!("1 B", parsed.to_string()); + } +} diff --git a/crates/yt/src/shared/mod.rs b/crates/yt/src/shared/mod.rs new file mode 100644 index 0000000..14e4949 --- /dev/null +++ b/crates/yt/src/shared/mod.rs @@ -0,0 +1 @@ +pub(crate) mod bytes; -- cgit 1.4.1