tangled
alpha
login
or
join now
da157.id
/
porcelain
0
fork
atom
cli dollcode encoder and decoder
0
fork
atom
overview
issues
pulls
pipelines
dollcode trait thing
0xda157
3 months ago
f9e68928
3717d902
+184
-84
6 changed files
expand all
collapse all
unified
split
Cargo.lock
Cargo.toml
lib-porcelain
Cargo.toml
src
deprecated.rs
lib.rs
src
main.rs
+2
-2
Cargo.lock
···
93
94
[[package]]
95
name = "lib-porcelain"
96
-
version = "0.1.0"
97
98
[[package]]
99
name = "once_cell_polyfill"
···
103
104
[[package]]
105
name = "porcelain"
106
-
version = "0.2.1"
107
dependencies = [
108
"clap",
109
"lib-porcelain",
···
93
94
[[package]]
95
name = "lib-porcelain"
96
+
version = "0.2.0"
97
98
[[package]]
99
name = "once_cell_polyfill"
···
103
104
[[package]]
105
name = "porcelain"
106
+
version = "0.2.2"
107
dependencies = [
108
"clap",
109
"lib-porcelain",
+2
-2
Cargo.toml
···
4
5
[package]
6
name = "porcelain"
7
-
version = "0.2.1"
8
license = "MIT"
9
authors = ["0xda157 <da157@voidq.com>"]
10
description = "cli dollcode encoder and decoder"
···
15
edition = "2024"
16
17
[dependencies]
18
-
lib-porcelain = { path = "./lib-porcelain", version = "0.1.0" }
19
clap = { version = "4.5.51", features = ["cargo"] }
···
4
5
[package]
6
name = "porcelain"
7
+
version = "0.2.2"
8
license = "MIT"
9
authors = ["0xda157 <da157@voidq.com>"]
10
description = "cli dollcode encoder and decoder"
···
15
edition = "2024"
16
17
[dependencies]
18
+
lib-porcelain = { path = "./lib-porcelain", version = "0.2.0" }
19
clap = { version = "4.5.51", features = ["cargo"] }
+1
-3
lib-porcelain/Cargo.toml
···
1
[package]
2
name = "lib-porcelain"
3
-
version = "0.1.0"
4
license = "MIT"
5
authors = ["0xda157 <da157@voidq.com>"]
6
description = "dollcode encoder and decoder"
7
homepage = "https://codeberg.org/da157/porcelain"
8
repository = "https://codeberg.org/da157/porcelain"
9
edition = "2024"
10
-
11
-
[dependencies]
···
1
[package]
2
name = "lib-porcelain"
3
+
version = "0.2.0"
4
license = "MIT"
5
authors = ["0xda157 <da157@voidq.com>"]
6
description = "dollcode encoder and decoder"
7
homepage = "https://codeberg.org/da157/porcelain"
8
repository = "https://codeberg.org/da157/porcelain"
9
edition = "2024"
0
0
+95
lib-porcelain/src/deprecated.rs
···
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
···
1
+
/// Decodes a `&str` containing a dollcode into a `u64`.
2
+
/// Returns `None` if `input` contains invalid characters
3
+
/// (everything except `'▖'`, `'▘'`, and `'▌'`).
4
+
///
5
+
/// # Example
6
+
///
7
+
/// ```
8
+
/// use lib_porcelain::dollcode_decode;
9
+
///
10
+
/// assert_eq!(dollcode_decode(""), Some(0));
11
+
///
12
+
/// assert_eq!(dollcode_decode("▖▖▘▘▌▘▌▌▘▘▘▌▌"), Some(893271));
13
+
///
14
+
/// assert_eq!(dollcode_decode("invalid"), None);
15
+
/// ```
16
+
#[deprecated(since = "0.2.0", note = "please use the `Dollcode` trait instead")]
17
+
pub fn dollcode_decode(input: &str) -> Option<u64> {
18
+
let mut acc = 0;
19
+
20
+
for char in input.chars() {
21
+
acc = acc * 3
22
+
+ match char {
23
+
'▖' => 1,
24
+
'▘' => 2,
25
+
'▌' => 3,
26
+
_ => return None,
27
+
}
28
+
}
29
+
30
+
Some(acc)
31
+
}
32
+
33
+
/// Takes a `u64` and encodes in to a `String` containing a dollcode made up of
34
+
/// `'▖'`, `'▘'`, and `'▌'`.
35
+
///
36
+
/// # Example
37
+
///
38
+
/// ```
39
+
/// use lib_porcelain::dollcode_encode;
40
+
///
41
+
/// assert_eq!(dollcode_encode(0), "");
42
+
///
43
+
/// assert_eq!(dollcode_encode(893271), "▖▖▘▘▌▘▌▌▘▘▘▌▌");
44
+
/// ```
45
+
#[deprecated(since = "0.2.0", note = "please use the `Dollcode` trait instead")]
46
+
pub fn dollcode_encode(mut input: u64) -> String {
47
+
let mut res = String::new();
48
+
49
+
while input > 0 {
50
+
input -= 1;
51
+
res.push(['▖', '▘', '▌'][(input % 3) as usize]);
52
+
input /= 3;
53
+
}
54
+
55
+
res.chars().rev().collect::<String>()
56
+
}
57
+
58
+
#[cfg(test)]
59
+
mod tests {
60
+
use crate::{dollcode_decode, dollcode_encode};
61
+
62
+
#[test]
63
+
fn test_encode() {
64
+
assert_eq!(dollcode_encode(0), "");
65
+
assert_eq!(dollcode_encode(1), "▖");
66
+
assert_eq!(dollcode_encode(2), "▘");
67
+
assert_eq!(dollcode_encode(3), "▌");
68
+
assert_eq!(dollcode_encode(4), "▖▖");
69
+
assert_eq!(dollcode_encode(13), "▖▖▖");
70
+
assert_eq!(dollcode_encode(440729), "▖▌▌▌▌▖▖▖▘▌▘▘");
71
+
assert_eq!(dollcode_encode(893271), "▖▖▘▘▌▘▌▌▘▘▘▌▌");
72
+
assert_eq!(
73
+
dollcode_encode(u64::MAX),
74
+
"▖▖▖▖▘▘▖▘▌▘▘▖▘▘▖▖▘▌▌▖▖▌▌▌▖▌▖▖▌▖▌▌▖▌▌▘▖▖▘▖▌"
75
+
);
76
+
}
77
+
78
+
#[test]
79
+
fn test_decode() {
80
+
assert_eq!(dollcode_decode("invalid"), None);
81
+
assert_eq!(dollcode_decode("▖▌▌▌▌▖▖▖▘invalid"), None);
82
+
assert_eq!(dollcode_decode(""), Some(0));
83
+
assert_eq!(dollcode_decode("▖"), Some(1));
84
+
assert_eq!(dollcode_decode("▘"), Some(2));
85
+
assert_eq!(dollcode_decode("▌"), Some(3));
86
+
assert_eq!(dollcode_decode("▖▖"), Some(4));
87
+
assert_eq!(dollcode_decode("▖▖▖"), Some(13));
88
+
assert_eq!(dollcode_decode("▖▌▌▌▌▖▖▖▘▌▘▘"), Some(440729));
89
+
assert_eq!(dollcode_decode("▖▖▘▘▌▘▌▌▘▘▘▌▌"), Some(893271));
90
+
assert_eq!(
91
+
dollcode_decode("▖▖▖▖▘▘▖▘▌▘▘▖▘▘▖▖▘▌▌▖▖▌▌▌▖▌▖▖▌▖▌▌▖▌▌▘▖▖▘▖▌"),
92
+
Some(u64::MAX)
93
+
);
94
+
}
95
+
}
+71
-68
lib-porcelain/src/lib.rs
···
1
-
/// Decodes a `&str` containing a dollcode into a `u64`.
2
-
/// Returns `None` if `input` contains invalid characters
3
-
/// (everything except `'▖'`, `'▘'`, and `'▌'`).
4
-
///
5
-
/// # Example
6
-
///
7
-
/// ```
8
-
/// use lib_porcelain::dollcode_decode;
9
-
///
10
-
/// assert_eq!(dollcode_decode(""), Some(0));
11
-
///
12
-
/// assert_eq!(dollcode_decode("▖▖▘▘▌▘▌▌▘▘▘▌▌"), Some(893271));
13
-
///
14
-
/// assert_eq!(dollcode_decode("invalid"), None);
15
-
/// ```
16
-
pub fn dollcode_decode(input: &str) -> Option<u64> {
17
-
let mut acc = 0;
18
19
-
for char in input.chars() {
20
-
acc = acc * 3
21
-
+ match char {
22
-
'▖' => 1,
23
-
'▘' => 2,
24
-
'▌' => 3,
25
-
_ => return None,
26
-
}
27
-
}
28
29
-
Some(acc)
0
0
0
0
0
0
0
0
0
0
30
}
31
32
-
/// Takes a `u64` and encodes in to a `String` containing a dollcode made up of
33
-
/// `'▖'`, `'▘'`, and `'▌'`.
34
-
///
35
-
/// # Example
36
-
///
37
-
/// ```
38
-
/// use lib_porcelain::dollcode_encode;
39
-
///
40
-
/// assert_eq!(dollcode_encode(0), "");
41
-
///
42
-
/// assert_eq!(dollcode_encode(893271), "▖▖▘▘▌▘▌▌▘▘▘▌▌");
43
-
/// ```
44
-
pub fn dollcode_encode(mut input: u64) -> String {
45
-
let mut res = String::new();
0
0
0
0
0
0
0
0
0
0
0
0
0
46
47
-
while input > 0 {
48
-
input -= 1;
49
-
res.push(['▖', '▘', '▌'][(input % 3) as usize]);
50
-
input /= 3;
51
}
0
52
53
-
res.chars().rev().collect::<String>()
54
-
}
0
0
0
0
55
56
#[cfg(test)]
57
mod tests {
58
-
use crate::{dollcode_decode, dollcode_encode};
59
60
#[test]
61
fn test_encode() {
62
-
assert_eq!(dollcode_encode(0), "");
63
-
assert_eq!(dollcode_encode(1), "▖");
64
-
assert_eq!(dollcode_encode(2), "▘");
65
-
assert_eq!(dollcode_encode(3), "▌");
66
-
assert_eq!(dollcode_encode(4), "▖▖");
67
-
assert_eq!(dollcode_encode(13), "▖▖▖");
68
-
assert_eq!(dollcode_encode(440729), "▖▌▌▌▌▖▖▖▘▌▘▘");
69
-
assert_eq!(dollcode_encode(893271), "▖▖▘▘▌▘▌▌▘▘▘▌▌");
70
assert_eq!(
71
-
dollcode_encode(u64::MAX),
72
"▖▖▖▖▘▘▖▘▌▘▘▖▘▘▖▖▘▌▌▖▖▌▌▌▖▌▖▖▌▖▌▌▖▌▌▘▖▖▘▖▌"
73
);
74
}
75
76
#[test]
77
fn test_decode() {
78
-
assert_eq!(dollcode_decode("invalid"), None);
79
-
assert_eq!(dollcode_decode("▖▌▌▌▌▖▖▖▘invalid"), None);
80
-
assert_eq!(dollcode_decode(""), Some(0));
81
-
assert_eq!(dollcode_decode("▖"), Some(1));
82
-
assert_eq!(dollcode_decode("▘"), Some(2));
83
-
assert_eq!(dollcode_decode("▌"), Some(3));
84
-
assert_eq!(dollcode_decode("▖▖"), Some(4));
85
-
assert_eq!(dollcode_decode("▖▖▖"), Some(13));
86
-
assert_eq!(dollcode_decode("▖▌▌▌▌▖▖▖▘▌▘▘"), Some(440729));
87
-
assert_eq!(dollcode_decode("▖▖▘▘▌▘▌▌▘▘▘▌▌"), Some(893271));
88
assert_eq!(
89
-
dollcode_decode("▖▖▖▖▘▘▖▘▌▘▘▖▘▘▖▖▘▌▌▖▖▌▌▌▖▌▖▖▌▖▌▌▖▌▌▘▖▖▘▖▌"),
90
Some(u64::MAX)
91
);
92
}
···
1
+
mod deprecated;
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
2
3
+
pub use deprecated::{dollcode_decode, dollcode_encode};
0
0
0
0
0
0
0
0
4
5
+
pub trait Dollcode {
6
+
/// Decodes a `&str` containing a dollcode into a `Self`.
7
+
/// Returns `None` if `dollcode` contains invalid characters
8
+
/// (everything except `'▖'`, `'▘'`, and `'▌'`).
9
+
fn from_dollcode(dollcode: &str) -> Option<Self>
10
+
where
11
+
Self: Sized;
12
+
13
+
/// Takes a `u64` and encodes in to a `String` containing a dollcode made up
14
+
/// of `'▖'`, `'▘'`, and `'▌'`.
15
+
fn to_dollcode(self) -> String;
16
}
17
18
+
macro_rules! impl_std_Dollcode {
19
+
(for $($t:ty),+) => {
20
+
$(impl Dollcode for $t {
21
+
fn from_dollcode(input: &str) -> Option<Self> {
22
+
let mut acc = 0;
23
+
24
+
for char in input.chars() {
25
+
acc = acc * 3
26
+
+ match char {
27
+
'▖' => 1,
28
+
'▘' => 2,
29
+
'▌' => 3,
30
+
_ => return None,
31
+
}
32
+
}
33
+
34
+
Some(acc)
35
+
}
36
+
37
+
fn to_dollcode(mut self) -> String {
38
+
let mut res = String::new();
39
+
40
+
while self > 0 {
41
+
self -= 1;
42
+
res.push(['▖', '▘', '▌'][(self % 3) as usize]);
43
+
self /= 3;
44
+
}
45
46
+
res.chars().rev().collect::<String>()
47
+
}
48
+
})*
0
49
}
50
+
}
51
52
+
impl_std_Dollcode!(for u8);
53
+
impl_std_Dollcode!(for u16);
54
+
impl_std_Dollcode!(for u32);
55
+
impl_std_Dollcode!(for u64);
56
+
impl_std_Dollcode!(for u128);
57
+
impl_std_Dollcode!(for usize);
58
59
#[cfg(test)]
60
mod tests {
61
+
use crate::Dollcode;
62
63
#[test]
64
fn test_encode() {
65
+
assert_eq!(0_u32.to_dollcode(), "");
66
+
assert_eq!(1_u32.to_dollcode(), "▖");
67
+
assert_eq!(2_u32.to_dollcode(), "▘");
68
+
assert_eq!(3_u32.to_dollcode(), "▌");
69
+
assert_eq!(4_u32.to_dollcode(), "▖▖");
70
+
assert_eq!(13_u32.to_dollcode(), "▖▖▖");
71
+
assert_eq!(440729_u32.to_dollcode(), "▖▌▌▌▌▖▖▖▘▌▘▘");
72
+
assert_eq!(893271_u32.to_dollcode(), "▖▖▘▘▌▘▌▌▘▘▘▌▌");
73
assert_eq!(
74
+
u64::MAX.to_dollcode(),
75
"▖▖▖▖▘▘▖▘▌▘▘▖▘▘▖▖▘▌▌▖▖▌▌▌▖▌▖▖▌▖▌▌▖▌▌▘▖▖▘▖▌"
76
);
77
}
78
79
#[test]
80
fn test_decode() {
81
+
assert_eq!(u32::from_dollcode("invalid"), None);
82
+
assert_eq!(u32::from_dollcode("▖▌▌▌▌▖▖▖▘invalid"), None);
83
+
assert_eq!(u32::from_dollcode(""), Some(0));
84
+
assert_eq!(u32::from_dollcode("▖"), Some(1));
85
+
assert_eq!(u32::from_dollcode("▘"), Some(2));
86
+
assert_eq!(u32::from_dollcode("▌"), Some(3));
87
+
assert_eq!(u32::from_dollcode("▖▖"), Some(4));
88
+
assert_eq!(u32::from_dollcode("▖▖▖"), Some(13));
89
+
assert_eq!(u32::from_dollcode("▖▌▌▌▌▖▖▖▘▌▘▘"), Some(440729));
90
+
assert_eq!(u32::from_dollcode("▖▖▘▘▌▘▌▌▘▘▘▌▌"), Some(893271));
91
assert_eq!(
92
+
u64::from_dollcode("▖▖▖▖▘▘▖▘▌▘▘▖▘▘▖▖▘▌▌▖▖▌▌▌▖▌▖▖▌▖▌▌▖▌▌▘▖▖▘▖▌"),
93
Some(u64::MAX)
94
);
95
}
+13
-9
src/main.rs
···
1
use clap::{ArgGroup, Command, Id, arg, command, crate_authors};
2
-
use lib_porcelain::{dollcode_decode, dollcode_encode};
3
4
fn main() {
5
let matches = command!()
···
25
if let Some(s) = input.strip_prefix("0x") {
26
println!(
27
"{}",
28
-
dollcode_encode(u64::from_str_radix(s, 16).expect("invalid hex"))
0
0
29
);
30
return;
31
}
···
33
if ematches.get_flag("hex") {
34
println!(
35
"{}",
36
-
dollcode_encode(u64::from_str_radix(input, 16).expect("invalid hex"))
0
0
37
);
38
return;
39
}
40
41
println!(
42
"{}",
43
-
dollcode_encode(
44
-
input
45
-
.parse::<u64>()
46
-
.expect("input must be declared as hex or be a decimial number")
47
-
)
48
);
49
}
50
51
if let Some(dmatches) = matches.subcommand_matches("decode") {
52
let dollcode = dmatches.get_one::<String>("dollcode").unwrap();
53
54
-
let res = dollcode_decode(dollcode).expect("dollcodes may only contain '▖', '▘', or '▌'");
0
55
56
match dmatches.get_one("format").map(Id::as_ref) {
57
Some("decimial") => println!("{}", res),
···
1
use clap::{ArgGroup, Command, Id, arg, command, crate_authors};
2
+
use lib_porcelain::Dollcode;
3
4
fn main() {
5
let matches = command!()
···
25
if let Some(s) = input.strip_prefix("0x") {
26
println!(
27
"{}",
28
+
u64::from_str_radix(s, 16)
29
+
.expect("invalid hex")
30
+
.to_dollcode()
31
);
32
return;
33
}
···
35
if ematches.get_flag("hex") {
36
println!(
37
"{}",
38
+
u64::from_str_radix(input, 16)
39
+
.expect("invalid hex")
40
+
.to_dollcode()
41
);
42
return;
43
}
44
45
println!(
46
"{}",
47
+
input
48
+
.parse::<u64>()
49
+
.expect("input must be declared as hex or be a decimial number")
50
+
.to_dollcode()
0
51
);
52
}
53
54
if let Some(dmatches) = matches.subcommand_matches("decode") {
55
let dollcode = dmatches.get_one::<String>("dollcode").unwrap();
56
57
+
let res =
58
+
u64::from_dollcode(dollcode).expect("dollcodes may only contain '▖', '▘', or '▌'");
59
60
match dmatches.get_one("format").map(Id::as_ref) {
61
Some("decimial") => println!("{}", res),