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