Skip to content

Commit 5c4e75b

Browse files
committed
Add a data module
This is a measure for computer information, it goes down to bits but the internal value is the octet. We decided against using the byte as the internal value because its size is architecture-dependent, on DSPs for example a byte could be 16 bits instead of 8 as it is usually understood. The octet on the other hand is always defined as eight bits.
1 parent 53ee48c commit 5c4e75b

File tree

4 files changed

+317
-0
lines changed

4 files changed

+317
-0
lines changed

src/data.rs

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
use super::measurement::*;
2+
3+
// Constants
4+
const OCTET_BIT_FACTOR: f64 = 0.125;
5+
6+
// Constants, legacy
7+
const OCTET_KILOOCTET_FACTOR: f64 = 1000.;
8+
const OCTET_MEGAOCTET_FACTOR: f64 = 1000000.;
9+
const OCTET_GIGAOCTET_FACTOR: f64 = 1000000000.;
10+
const OCTET_TERAOCTET_FACTOR: f64 = 1000000000000.;
11+
12+
// Constants, SI
13+
const OCTET_KIBIOCTET_FACTOR: f64 = 1024.;
14+
const OCTET_MEBIOCTET_FACTOR: f64 = 1048576.;
15+
const OCTET_GIBIOCTET_FACTOR: f64 = 1073741824.;
16+
const OCTET_TEBIOCTET_FACTOR: f64 = 1099511627776.;
17+
18+
/// The `Data` struct can be used to deal with computer information in a common way.
19+
/// Common legacy and SI units are supported.
20+
///
21+
/// # Example
22+
///
23+
/// ```
24+
/// use measurements::Data;
25+
///
26+
/// let file_size = Data::from_mebioctets(2.5);
27+
/// let octets = file_size.as_octets();
28+
/// println!("There are {} octets in that file.", octets);
29+
/// ```
30+
#[derive(Copy, Clone, Debug)]
31+
pub struct Data {
32+
octets: f64,
33+
}
34+
35+
impl Data {
36+
// Inputs
37+
pub fn from_octets(octets: f64) -> Self {
38+
Data { octets: octets }
39+
}
40+
41+
pub fn from_bits(bits: f64) -> Self {
42+
Self::from_octets(bits * OCTET_BIT_FACTOR)
43+
}
44+
45+
// Inputs, legacy
46+
pub fn from_kilooctets(kilooctets: f64) -> Self {
47+
Self::from_octets(kilooctets * OCTET_KILOOCTET_FACTOR)
48+
}
49+
50+
pub fn from_megaoctets(megaoctets: f64) -> Self {
51+
Self::from_octets(megaoctets * OCTET_MEGAOCTET_FACTOR)
52+
}
53+
54+
pub fn from_gigaoctets(gigaoctets: f64) -> Self {
55+
Self::from_octets(gigaoctets * OCTET_GIGAOCTET_FACTOR)
56+
}
57+
58+
pub fn from_teraoctets(teraoctets: f64) -> Self {
59+
Self::from_octets(teraoctets * OCTET_TERAOCTET_FACTOR)
60+
}
61+
62+
// Inputs, SI
63+
pub fn from_kibioctets(kibioctets: f64) -> Self {
64+
Self::from_octets(kibioctets * OCTET_KIBIOCTET_FACTOR)
65+
}
66+
67+
pub fn from_mebioctets(mebioctets: f64) -> Self {
68+
Self::from_octets(mebioctets * OCTET_MEBIOCTET_FACTOR)
69+
}
70+
71+
pub fn from_gibioctets(gibioctets: f64) -> Self {
72+
Self::from_octets(gibioctets * OCTET_GIBIOCTET_FACTOR)
73+
}
74+
75+
pub fn from_tebioctets(tebioctets: f64) -> Self {
76+
Self::from_octets(tebioctets * OCTET_TEBIOCTET_FACTOR)
77+
}
78+
79+
// Outputs
80+
pub fn as_octets(&self) -> f64 {
81+
self.octets
82+
}
83+
84+
pub fn as_bits(&self) -> f64 {
85+
self.octets / OCTET_BIT_FACTOR
86+
}
87+
88+
// Outputs, legacy
89+
pub fn as_kilooctets(&self) -> f64 {
90+
self.octets / OCTET_KILOOCTET_FACTOR
91+
}
92+
93+
pub fn as_megaoctets(&self) -> f64 {
94+
self.octets / OCTET_MEGAOCTET_FACTOR
95+
}
96+
97+
pub fn as_gigaoctets(&self) -> f64 {
98+
self.octets / OCTET_GIGAOCTET_FACTOR
99+
}
100+
101+
pub fn as_teraoctets(&self) -> f64 {
102+
self.octets / OCTET_TERAOCTET_FACTOR
103+
}
104+
105+
// Outputs, SI
106+
pub fn as_kibioctets(&self) -> f64 {
107+
self.octets / OCTET_KIBIOCTET_FACTOR
108+
}
109+
110+
pub fn as_mebioctets(&self) -> f64 {
111+
self.octets / OCTET_MEBIOCTET_FACTOR
112+
}
113+
114+
pub fn as_gibioctets(&self) -> f64 {
115+
self.octets / OCTET_GIBIOCTET_FACTOR
116+
}
117+
118+
pub fn as_tebioctets(&self) -> f64 {
119+
self.octets / OCTET_TEBIOCTET_FACTOR
120+
}
121+
}
122+
123+
impl Measurement for Data {
124+
fn get_base_units(&self) -> f64 {
125+
self.octets
126+
}
127+
128+
fn from_base_units(units: f64) -> Self {
129+
Self::from_octets(units)
130+
}
131+
}
132+
133+
implement_measurement! { Data }
134+
135+
impl ::std::fmt::Display for Data {
136+
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
137+
write!(f, "{:.1} o", self.as_octets())
138+
}
139+
}

src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ pub use volume::Volume;
2222
mod pressure;
2323
pub use pressure::Pressure;
2424

25+
#[allow(dead_code)]
26+
mod data;
27+
pub use data::Data;
28+
2529
// Include when running tests, but don't export them
2630
#[cfg(test)]
2731
#[allow(dead_code)]

src/tests/data_tests.rs

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
use data::*;
2+
use super::assert_almost_eq;
3+
4+
// Metric
5+
#[test]
6+
fn bits() {
7+
let i1 = Data::from_octets(100.0);
8+
let r1 = i1.as_bits();
9+
10+
let i2 = Data::from_bits(100.0);
11+
let r2 = i2.as_octets();
12+
13+
assert_almost_eq(r1, 800.0);
14+
assert_almost_eq(r2, 12.5);
15+
}
16+
17+
#[test]
18+
fn kilooctet() {
19+
let i1 = Data::from_octets(100.0);
20+
let r1 = i1.as_kilooctets();
21+
22+
let i2 = Data::from_kilooctets(100.0);
23+
let r2 = i2.as_octets();
24+
25+
assert_almost_eq(r1, 0.1);
26+
assert_almost_eq(r2, 1e5);
27+
}
28+
29+
#[test]
30+
fn megaoctet() {
31+
let i1 = Data::from_octets(100.0);
32+
let r1 = i1.as_megaoctets();
33+
34+
let i2 = Data::from_megaoctets(100.0);
35+
let r2 = i2.as_octets();
36+
37+
assert_almost_eq(r1, 0.0001);
38+
assert_almost_eq(r2, 1e8);
39+
}
40+
41+
#[test]
42+
fn gigaoctet() {
43+
let i1 = Data::from_octets(100.0);
44+
let r1 = i1.as_gigaoctets();
45+
46+
let i2 = Data::from_gigaoctets(100.0);
47+
let r2 = i2.as_octets();
48+
49+
assert_almost_eq(r1, 1e-7);
50+
assert_almost_eq(r2, 1e11);
51+
}
52+
53+
#[test]
54+
fn teraoctet() {
55+
let i1 = Data::from_octets(100.0);
56+
let r1 = i1.as_teraoctets();
57+
58+
let i2 = Data::from_teraoctets(100.0);
59+
let r2 = i2.as_octets();
60+
61+
assert_almost_eq(r1, 1e-10);
62+
assert_almost_eq(r2, 1e14);
63+
}
64+
65+
// Imperial
66+
#[test]
67+
fn kibioctet() {
68+
let i1 = Data::from_octets(100.0);
69+
let r1 = i1.as_kibioctets();
70+
71+
let i2 = Data::from_kibioctets(100.0);
72+
let r2 = i2.as_octets();
73+
74+
assert_almost_eq(r1, 0.09765625);
75+
assert_almost_eq(r2, 102400.0);
76+
}
77+
78+
#[test]
79+
fn mebioctet() {
80+
let i1 = Data::from_octets(100.0);
81+
let r1 = i1.as_mebioctets();
82+
83+
let i2 = Data::from_mebioctets(100.0);
84+
let r2 = i2.as_octets();
85+
86+
assert_almost_eq(r1, 9.536743e-5);
87+
assert_almost_eq(r2, 104857600.0);
88+
}
89+
90+
#[test]
91+
fn gibioctets() {
92+
let i1 = Data::from_octets(100.0);
93+
let r1 = i1.as_gibioctets();
94+
95+
let i2 = Data::from_gibioctets(100.0);
96+
let r2 = i2.as_octets();
97+
98+
assert_almost_eq(r1, 9.313226e-8);
99+
assert_almost_eq(r2, 107374182400.0);
100+
}
101+
102+
#[test]
103+
fn tebioctets() {
104+
let i1 = Data::from_octets(100.0);
105+
let r1 = i1.as_tebioctets();
106+
107+
let i2 = Data::from_tebioctets(100.0);
108+
let r2 = i2.as_octets();
109+
110+
assert_almost_eq(r1, 9.094947e-11);
111+
assert_almost_eq(r2, 109951162777600.0);
112+
}
113+
114+
// Traits
115+
#[test]
116+
fn add() {
117+
let a = Data::from_octets(2.0);
118+
let b = Data::from_octets(4.0);
119+
let c = a + b;
120+
assert_almost_eq(c.as_octets(), 6.0);
121+
}
122+
123+
#[test]
124+
fn sub() {
125+
let a = Data::from_octets(2.0);
126+
let b = Data::from_octets(4.0);
127+
let c = a - b;
128+
assert_almost_eq(c.as_octets(), -2.0);
129+
}
130+
131+
#[test]
132+
fn mul() {
133+
let a = Data::from_octets(2.0);
134+
let b = Data::from_octets(4.0);
135+
let c = a * b;
136+
let d = b * 2.0;
137+
assert_almost_eq(c.as_octets(), 8.0);
138+
assert_almost_eq(d.as_octets(), 8.0);
139+
}
140+
141+
#[test]
142+
fn div() {
143+
let a = Data::from_octets(2.0);
144+
let b = Data::from_octets(4.0);
145+
let c = a * b;
146+
let d = a * 2.0;
147+
assert_almost_eq(c.as_octets(), 8.0);
148+
assert_almost_eq(d.as_octets(), 4.0);
149+
}
150+
151+
#[test]
152+
fn eq() {
153+
let a = Data::from_octets(2.0);
154+
let b = Data::from_octets(2.0);
155+
assert_eq!(a == b, true);
156+
}
157+
158+
#[test]
159+
fn neq() {
160+
let a = Data::from_octets(2.0);
161+
let b = Data::from_octets(4.0);
162+
assert_eq!(a == b, false);
163+
}
164+
165+
#[test]
166+
fn cmp() {
167+
let a = Data::from_octets(2.0);
168+
let b = Data::from_octets(4.0);
169+
assert_eq!(a < b, true);
170+
assert_eq!(a <= b, true);
171+
assert_eq!(a > b, false);
172+
assert_eq!(a >= b, false);
173+
}

src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ mod length_tests;
22
mod temperature_tests;
33
mod weight_tests;
44
mod volume_tests;
5+
mod data_tests;
56

67
const DEFAULT_DELTA: f64 = 0.00001;
78

0 commit comments

Comments
 (0)