cock_cli/
lib.rs

1/// This module contains functions that are used in operations within main.rs and other binaries.
2
3/// This function prompts the user for input and returns the input as a string.
4fn prompt(msg: &str) -> String {
5    println!("{}\n", msg);
6    let mut input = String::new();
7    print!(">> ");
8
9    use std::io::{self, Write};
10    io::stdout().flush().unwrap();
11
12    io::stdin()
13        .read_line(&mut input)
14        .expect("Failed to read line");
15
16    input.trim().to_string()
17}
18
19/// This function parses a string to an integer.
20fn parse_to_int(input: &str, default: i32) -> i32 {
21    match input.parse::<i32>() {
22        Ok(n) => n,
23        Err(_) => default,
24    }
25}
26
27/// This function parses a string to a float.
28fn parse_to_float(input: &str, default: f32) -> f32 {
29    match input.parse::<f32>() {
30        Ok(n) => n,
31        Err(_) => default,
32    }
33}
34
35/// This function prompts the user to choose from a menu and returns the choice as a string.
36fn choose_from_menu(choices: Vec<String>, msg: &str) -> String {
37    println!("Please choose an option:\n");
38
39    let choice_len = choices.len().try_into().expect("Too many choices.");
40
41    for (i, choice) in choices.iter().enumerate() {
42        println!("{}. {}", i + 1, choice);
43    }
44
45    println!();
46
47    let selection = loop {
48        let choice = prompt(msg);
49        let choice = parse_to_int(&choice, 0);
50
51        if choice > 0 && choice <= choice_len {
52            break (choice - 1) as usize;
53        } else {
54            println!("Invalid choice.");
55        }
56    };
57
58    choices.get(selection).unwrap().to_string()
59}
60
61use cock_lib::{
62    cock_parts::{Abnormalities, Curvature, Size, SizeType},
63    FromString, GetVariants, InnerUser, ID
64};
65
66/// This function prompts the user to choose from a menu consisting of the variants of the type `T` and returns the `T` variant chosen.
67fn input<T: GetVariants + FromString>(message: &str) -> T {
68    let choice = choose_from_menu(T::get_variants(), message);
69    let variant = T::from_string(&choice);
70    clear_screen();
71    variant
72}
73
74/// This function is responsible for getting the user's [ID] parameters.
75fn get_user() -> ID {
76    let user_type = choose_from_menu(ID::get_variants(), "ID type:");
77    let user = match user_type.as_str() {
78        "Anonymous" => ID::Anonymous,
79        "User" => {
80            clear_screen();
81            let name = prompt("User Name:");
82            clear_screen();
83            let discord_name = prompt("Discord Name:");
84            ID::User(InnerUser { name, discord_name })
85        }
86        _ => panic!("Invalid user type"),
87    };
88    clear_screen();
89    user
90}
91
92/// This function is responsible for getting the cock [Size] parameters.
93fn get_size() -> Size {
94    let size_type = choose_from_menu(SizeType::get_variants(), "Inches or Centimeters?");
95    let length = parse_to_float(prompt("Cock length:").as_str(), 0.0);
96    let girth = parse_to_float(prompt("Cock girth:").as_str(), 0.0);
97
98    let size = match size_type.as_str() {
99        "Inches" => Size::from_in(length, girth),
100        "Centimeters" => Size::from_cm(length, girth),
101        _ => panic!("Invalid size type"),
102    };
103    clear_screen();
104    size
105}
106
107/// Fn to clear terminal and reset cursor position
108fn clear_screen() {
109    print!("{esc}[2J{esc}[1;1H", esc = 27 as char);
110}
111
112use cock_lib::{CockHandler, CockStruct, cock_parts::Shape};
113
114/// Used to prompt a user for each necessary cock attribute and construct a CockStruct from them.
115pub fn cock_handler_build() -> CockHandler {
116    let id = get_user();
117    let size = get_size();
118    let aesthetic = input("Choose aesthetic:");
119    let balls = input("Choose ball size:");
120    let shape = {
121        let in_shape = input("Choose cock shape:");
122        match in_shape {
123            Shape::Other(_) => {
124                let val = prompt("Define the shape:");
125                clear_screen();
126                Shape::Other(val)
127            }
128            _ => in_shape,
129        }
130    };
131    let curvature = {
132        let in_curv = input("Choose cock curvature:");
133        match in_curv {
134            Curvature::Other(_) => {
135                let val = prompt("Define the curvature:");
136                clear_screen();
137                Curvature::Other(val)
138            }
139            _ => in_curv,
140        }
141    };
142    let circumcision = input("Choose cirumcision status:");
143    let veininess = input("Choose veininess level:");
144    let abnormalities = {
145        let in_abnor = input("Choose cock abnormalities:");
146        match in_abnor {
147            Abnormalities::Major(_) => {
148                let val = prompt("Define the major abnormalities:");
149                clear_screen();
150                Abnormalities::Major(val)
151            }
152            Abnormalities::Minor(_) => {
153                let val = prompt("Define the minor abnormalities:");
154                clear_screen();
155                Abnormalities::Minor(val)
156            }
157            _ => in_abnor,
158        }
159    };
160
161    let cock = CockStruct {
162        size,
163        aesthetic,
164        balls,
165        shape,
166        curvature,
167        circumcision,
168        veininess,
169        abnormalities,
170    };
171
172    CockHandler { id, cock }
173}