Code Style

Краен срок
08.11.2018 17:00
Точки
1

Срокът за предаване на решения е отминал

extern crate solution;
use solution::*;
#[test]
fn test_invalid() {
assert_eq!("some-var".parse::<CodeStyle>(), Err(CodeStyleError::InvalidChar('-')));
assert_eq!("some var".parse::<CodeStyle>(), Err(CodeStyleError::InvalidChar(' ')));
assert_eq!("+_+".parse::<CodeStyle>(), Err(CodeStyleError::InvalidFirstChar('+')));
assert_eq!("❤️_❤️".parse::<CodeStyle>(), Err(CodeStyleError::InvalidFirstChar('❤')));
assert_eq!("123abc".parse::<CodeStyle>(), Err(CodeStyleError::InvalidFirstChar('1')));
assert_eq!("a+b=c".parse::<CodeStyle>(), Err(CodeStyleError::InvalidChar('+')));
}
#[test]
fn test_valid() {
assert_eq!("abc123".parse::<CodeStyle>(), Ok(CodeStyle::Unknown));
assert_eq!("singleword".parse::<CodeStyle>(), Ok(CodeStyle::Unknown));
assert_eq!("иманяма".parse::<CodeStyle>(), Ok(CodeStyle::Unknown));
assert_eq!("some_var".parse::<CodeStyle>(), Ok(CodeStyle::Underscored));
assert_eq!(" some_var ".parse::<CodeStyle>(), Ok(CodeStyle::Underscored));
assert_eq!("пиле_със_зеле".parse::<CodeStyle>(), Ok(CodeStyle::Underscored));
assert_eq!("someVar".parse::<CodeStyle>(), Ok(CodeStyle::Camelcased));
assert_eq!("SomeVar".parse::<CodeStyle>(), Ok(CodeStyle::Camelcased));
assert_eq!("HELLO_WORLD".parse::<CodeStyle>(), Ok(CodeStyle::ScreamingSnakecased));
assert_eq!("SomeVar".parse::<CodeStyle>(), Ok(CodeStyle::Camelcased));
assert_eq!("Hello_World".parse::<CodeStyle>(), Ok(CodeStyle::Mixed));
assert_eq!("SomeVar_".parse::<CodeStyle>(), Ok(CodeStyle::Mixed));
}

Целта на задачата е да напишем едно малко тематично допълнение към домашно 1. В идеалния вариант, не бихме очаквали само идентификатори с подчертавки, а бихме засякли какъв стил идентификатор се подава. Това искаме да направите.

Възможните варианти са:

  • CodeStyle::Underscored: малки символи, разделени с (колкото и да е, но поне една) подчертавки. Примерно: some_var, some___var_
  • CodeStyle::ScreamingSnakecased: големи символи, разделени с (колкото и да е, може и нула) подчертавки. Например: SOME_VAR, SOME___VAR_
  • CodeStyle::Camelcased: само малки и големи символи (никакви подчертавки): SomeVar, someVar
  • CodeStyle::Mixed: комбинация от малки и големи символи, и подчертавки: Some_Var, someVar_
  • CodeStyle::Unknown: само малки символи -- няма как да преценим дали е underscored или camelcased, ако няма индикатор за смяна на "думата". Пример: "somevar", "патладжан".

Забележете, че SOMEVAR е ScreamingSnakecased, а не Unknown, защото приемаме, че няма как да е camelcased, така че няма двусмислие.

"Символ" се дефинира както при първото домашно, като вкарваме error handling:

  • Първия символ трябва да е задължително буква. Ако не е, връщаме CodeStyleError::InvalidFirstChar, конструиран със символа.
  • Всеки следващ символ може да е буква, цифра, или _. Ако не е, връщаме CodeStyleError::InvalidChar, конструиран със символа.

Дефинираме "буква" като: това, за което char::is_alphabetic върне истина. Дефинираме "цифра" като: това, за което char::is_numeric върне истина.

В случай, че подадем празен низ (след нормализация на входа), очакваме грешка CodeStyleError::EmptyString.

Нормализация на входа

Ако ви подадем низ с интервали, табове, или нови редове преди или след идентификатора, изчистете ги. Тоест, тези две са еквивалентни:

let code_style = CodeStyle::from_str(" some_var ");
let code_style = CodeStyle::from_str("some_var");

(Впрочем, което е еквивалентно на:)

let code_style = "some_var".parse::<CodeStyle>();

Структурата на кода, която очакваме:

use std::str::FromStr;

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
    Underscored,
    Camelcased,
    ScreamingSnakecased,
    Unknown,
    Mixed
}

#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
    EmptyString,
    InvalidFirstChar(char),
    InvalidChar(char),
}

impl FromStr for CodeStyle {
    type Err = CodeStyleError;

    fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
        unimplemented!()
    }
}

Внимавайте за кирилица и друг unicode! Напишете си тестове, които упражняват по-особени символи! Четете документацията на char, str, и каквито други линкове има в тях.

Решения

Андрей
  • Коректно
  • 2 успешни тест(а)
  • 0 неуспешни тест(а)
Андрей

use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
Underscored,
Camelcased,
ScreamingSnakecased,
Unknown,
Mixed
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
EmptyString,
InvalidFirstChar(char),
InvalidChar(char),
}
impl FromStr for CodeStyle {
type Err = CodeStyleError;
fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
let identifier = identifier.trim();
let first_char = identifier.chars().next().ok_or(CodeStyleError::EmptyString)?;
if !first_char.is_alphabetic() {
return Err(CodeStyleError::InvalidFirstChar(first_char));
}
let mut uppercase = false;
let mut lowercase = false;
let mut underscore = false;
for c in identifier.chars() {
if c == '_' {
underscore = true;
} else if c.is_lowercase() {
lowercase = true;
} else if c.is_uppercase() {
uppercase = true;
} else if !c.is_alphanumeric() {
return Err(CodeStyleError::InvalidChar(c))
}
}
Ok(match (underscore, lowercase, uppercase) {
(true, true, false) => CodeStyle::Underscored,
(true, false, true) => CodeStyle::ScreamingSnakecased,
(false, true, true) => CodeStyle::Camelcased,
(true, true, true) => CodeStyle::Mixed,
_ => CodeStyle::Unknown,
})
}
}
Compiling solution v0.1.0 (file:///tmp/d20181108-22631-1mda9gt/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.24s
     Running target/debug/deps/solution-7017bcc2d31a1134

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-773f144f21eb3f81

running 2 tests
test solution_test::test_invalid ... ok
test solution_test::test_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Ива Милушева
  • Коректно
  • 2 успешни тест(а)
  • 0 неуспешни тест(а)
Ива Милушева

use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
Underscored,
Camelcased,
ScreamingSnakecased,
Unknown,
Mixed
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
EmptyString,
InvalidFirstChar(char),
InvalidChar(char),
}
impl FromStr for CodeStyle {
type Err = CodeStyleError;
fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
let identifier = identifier.trim();
if identifier == "" {
return Err(CodeStyleError::EmptyString);
}
let first_char = identifier.chars().next().unwrap();
if !first_char.is_alphabetic() {
return Err(CodeStyleError::InvalidFirstChar(first_char))
}
let mut contains_underscore = false;
let mut contains_upper = false;
let mut contains_lower = false;
for c in identifier.chars() {
if c == '_' {
contains_underscore = true;
}
else if !c.is_alphanumeric() {
return Err(CodeStyleError::InvalidChar(c));
}
else if !c.is_numeric() {
if c.to_string().to_uppercase() == c.to_string() {
contains_upper = true;
}
else if c.to_string().to_lowercase() == c.to_string() {
contains_lower = true;
}
}
}
if contains_underscore {
if contains_upper && !contains_lower {
return Ok(CodeStyle::ScreamingSnakecased);
}
else if !contains_upper {
return Ok(CodeStyle::Underscored);
}
return Ok(CodeStyle::Mixed);
}
else if contains_upper {
return Ok(CodeStyle::Camelcased);
}
return Ok(CodeStyle::Unknown);
}
}
Compiling solution v0.1.0 (file:///tmp/d20181108-22631-178j7t5/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.56s
     Running target/debug/deps/solution-7017bcc2d31a1134

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-773f144f21eb3f81

running 2 tests
test solution_test::test_invalid ... ok
test solution_test::test_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Даяна Веселинова
  • Коректно
  • 2 успешни тест(а)
  • 0 неуспешни тест(а)
Даяна Веселинова

use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
Underscored,
Camelcased,
ScreamingSnakecased,
Unknown,
Mixed
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
EmptyString,
InvalidFirstChar(char),
InvalidChar(char),
}
impl FromStr for CodeStyle {
type Err = CodeStyleError;
fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
let mut bool_under_scored = true;
let mut bool_screaming_case=true;
let mut bool_camel_case=true;
let mut bool_big_letter=false;
let mut bool_small_letter=false;
let identifier=identifier.trim();
if identifier.is_empty() {
return Err(CodeStyleError::EmptyString);
}
let first_char = identifier.trim().chars().next().unwrap();
if !first_char.is_alphabetic(){
return Err(CodeStyleError::InvalidFirstChar(first_char));
}
for m in identifier.chars(){
if m.is_alphabetic() || m.is_numeric() || m=='_' {
continue;
} else {
return Err(CodeStyleError::InvalidChar(m));
}
}
for m in identifier.chars(){
if m.is_lowercase() || m =='_' || m.is_numeric(){
continue;
} else {
bool_under_scored=false;
}
}
for m in identifier.chars(){
if m.is_uppercase() || m=='_' || m.is_numeric(){
continue;
} else {
bool_screaming_case=false;
}
}
for m in identifier.chars(){
if m.is_uppercase() || m.is_lowercase() || m.is_numeric() && m!='_' {
if m.is_lowercase() {
bool_small_letter=true;
}
if m.is_uppercase() {
bool_big_letter=true;
}
continue;
} else {
bool_camel_case=false;
}
}
if bool_under_scored && identifier.contains("_") {
return Ok(CodeStyle::Underscored);
}
if bool_screaming_case{
return Ok(CodeStyle::ScreamingSnakecased);
}
if bool_camel_case && bool_small_letter && bool_big_letter {
return Ok(CodeStyle::Camelcased);
}
if bool_big_letter && bool_small_letter && identifier.contains("_") {
return Ok(CodeStyle::Mixed);
}
Ok(CodeStyle::Unknown)
}
}
Compiling solution v0.1.0 (file:///tmp/d20181108-22631-yqbe0j/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.34s
     Running target/debug/deps/solution-7017bcc2d31a1134

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-773f144f21eb3f81

running 2 tests
test solution_test::test_invalid ... ok
test solution_test::test_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Николай Данаилов
  • Коректно
  • 2 успешни тест(а)
  • 0 неуспешни тест(а)
Николай Данаилов

use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
Underscored,
Camelcased,
ScreamingSnakecased,
Unknown,
Mixed
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
EmptyString,
InvalidFirstChar(char),
InvalidChar(char),
}
fn validate(identifier: &str) -> Option<CodeStyleError> {
let mut iterator = identifier.chars();
let first_char = iterator.next();
if first_char.is_none() {
return Some(CodeStyleError::EmptyString);
}
let first_char_unwrapped = first_char.unwrap();
if !first_char_unwrapped.is_alphabetic() {
return Some(CodeStyleError::InvalidFirstChar(first_char_unwrapped));
}
for c in iterator {
if !c.is_alphanumeric() && c != '_' {
return Some(CodeStyleError::InvalidChar(c));
}
}
None
}
fn parse_identifier(identifier: &str) -> (bool, bool, bool) {
let mut lowercase = false;
let mut uppercase = false;
let mut underscore = false;
for c in identifier.chars() {
if c.is_lowercase() {
lowercase = true;
}
else if c.is_uppercase() {
uppercase = true;
}
else if c == '_' {
underscore = true;
}
}
(lowercase, uppercase, underscore)
}
impl From<(bool, bool, bool)> for CodeStyle {
fn from(bool_tuple: (bool, bool, bool)) -> CodeStyle {
let (lowercase, uppercase, underscore) = bool_tuple;
if lowercase {
if uppercase {
if underscore {
return CodeStyle::Mixed;
}
else {
return CodeStyle::Camelcased;
}
} else {
if underscore {
return CodeStyle::Underscored;
}
}
}
else {
if uppercase {
return CodeStyle::ScreamingSnakecased;
}
}
CodeStyle::Unknown
}
}
impl FromStr for CodeStyle {
type Err = CodeStyleError;
fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
let processed_identifier = identifier.trim();
let validation_error = validate(processed_identifier);
if validation_error.is_some() {
return Err(validation_error.unwrap());
}
let parsing_result = parse_identifier(processed_identifier);
Ok(CodeStyle::from(parsing_result))
}
}
Compiling solution v0.1.0 (file:///tmp/d20181108-22631-1il5clt/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.29s
     Running target/debug/deps/solution-7017bcc2d31a1134

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-773f144f21eb3f81

running 2 tests
test solution_test::test_invalid ... ok
test solution_test::test_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Даниела Русева
  • Коректно
  • 2 успешни тест(а)
  • 0 неуспешни тест(а)
Даниела Русева

use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
Underscored,
Camelcased,
ScreamingSnakecased,
Unknown,
Mixed
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
EmptyString,
InvalidFirstChar(char),
InvalidChar(char),
}
impl FromStr for CodeStyle {
type Err = CodeStyleError;
fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
let identifier = identifier.trim();
match identifier.chars().next() {
Some(c) if !c.is_alphabetic() => return Err(CodeStyleError::InvalidFirstChar(c)),
None => return Err(CodeStyleError::EmptyString),
_ => (),
}
let mut contains_underscore = false;
let mut contains_lowercase_character = false;
let mut contains_uppercase_character = false;
for c in identifier.chars() {
if c == '_' {
contains_underscore = true;
} else if c.is_alphanumeric() {
if c.is_lowercase() {
contains_lowercase_character = true;
}
if c.is_uppercase() {
contains_uppercase_character = true;
}
} else {
return Err(CodeStyleError::InvalidChar(c));
}
}
if contains_underscore {
if contains_lowercase_character & contains_uppercase_character {
return Ok(CodeStyle::Mixed);
} else if contains_uppercase_character {
return Ok(CodeStyle::ScreamingSnakecased);
} else {
return Ok(CodeStyle::Underscored);
}
} else {
if contains_lowercase_character & contains_uppercase_character {
return Ok(CodeStyle::Camelcased);
} else if contains_uppercase_character {
return Ok(CodeStyle::ScreamingSnakecased);
} else {
return Ok(CodeStyle::Unknown);
}
}
}
}
Compiling solution v0.1.0 (file:///tmp/d20181108-22631-1mt96vs/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.63s
     Running target/debug/deps/solution-7017bcc2d31a1134

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-773f144f21eb3f81

running 2 tests
test solution_test::test_invalid ... ok
test solution_test::test_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Петко Георгиев
  • Коректно
  • 2 успешни тест(а)
  • 0 неуспешни тест(а)
Петко Георгиев

use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
Underscored,
Camelcased,
ScreamingSnakecased,
Unknown,
Mixed
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
EmptyString,
InvalidFirstChar(char),
InvalidChar(char),
}
impl FromStr for CodeStyle {
type Err = CodeStyleError;
fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
let identifier = identifier.trim();
if identifier.is_empty() {
return Err(CodeStyleError::EmptyString)
}
#[derive(PartialEq)]
enum Case {
None,
Upper,
Lower,
Mixed
};
let mut case = Case::None;
let mut contains_underscores = false;
// Check if the first character is alphabetic
{
let first_char = identifier.chars().next().unwrap();
if !first_char.is_alphabetic() {
return Err(CodeStyleError::InvalidFirstChar(first_char));
}
}
for c in identifier.chars() {
if c.is_alphabetic() {
let current_case;
if c.is_lowercase() {
current_case = Case::Lower;
} else {
current_case = Case::Upper;
}
if case == Case::None {
case = current_case
} else if case != current_case {
case = Case::Mixed;
}
} else if c == '_' {
contains_underscores = true;
} else if !c.is_numeric() {
return Err(CodeStyleError::InvalidChar(c));
}
}
if contains_underscores {
return match case {
Case::Lower => Ok(CodeStyle::Underscored),
Case::Upper => Ok(CodeStyle::ScreamingSnakecased),
Case::Mixed => Ok(CodeStyle::Mixed),
_ => unreachable!(),
};
} else {
return match case {
Case::Lower => Ok(CodeStyle::Unknown),
Case::Upper => Ok(CodeStyle::ScreamingSnakecased),
Case::Mixed => Ok(CodeStyle::Camelcased),
_ => unreachable!(),
};
}
}
}
Compiling solution v0.1.0 (file:///tmp/d20181108-22631-8ieeo0/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.33s
     Running target/debug/deps/solution-7017bcc2d31a1134

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-773f144f21eb3f81

running 2 tests
test solution_test::test_invalid ... ok
test solution_test::test_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Милен Дончев
  • Коректно
  • 2 успешни тест(а)
  • 0 неуспешни тест(а)
Милен Дончев

use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
Underscored,
Camelcased,
ScreamingSnakecased,
Unknown,
Mixed
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
EmptyString,
InvalidFirstChar(char),
InvalidChar(char),
}
impl FromStr for CodeStyle {
type Err = CodeStyleError;
fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
let identifier = identifier.trim();
let mut is_there_lower_cased = false;
let mut is_there_upper_cased = false;
let mut is_there_delimiter = false;
if identifier.is_empty() {
return Err(CodeStyleError::EmptyString);
}
let i = identifier.chars().next().unwrap();
if !i.is_alphabetic() {
return Err(CodeStyleError::InvalidFirstChar(i));
}
for i in identifier.chars() {
if i != '_' && !i.is_alphabetic() && !i.is_numeric() {
return Err(CodeStyleError::InvalidChar(i));
}
}
for i in identifier.chars() {
if i.is_lowercase() {
is_there_lower_cased = true;
}
if i.is_uppercase() {
is_there_upper_cased = true;
}
if i == '_' {
is_there_delimiter = true;
}
}
if contains_only_low(identifier) && is_there_delimiter {
return Ok(CodeStyle::Underscored);
}
if contains_only_upper(identifier) {
return Ok(CodeStyle::ScreamingSnakecased);
}
if is_there_delimiter == false && is_there_lower_cased && is_there_upper_cased {
return Ok(CodeStyle::Camelcased);
}
if is_there_delimiter && is_there_lower_cased && is_there_upper_cased {
return Ok(CodeStyle::Mixed);
}
if is_there_delimiter == false && contains_only_low(identifier) {
return Ok(CodeStyle::Unknown);
}
return Ok(CodeStyle::Unknown);
}
}
fn contains_only_low(iden: &str) -> bool {
for i in iden.chars() {
if !i.is_lowercase() && i != '_' && !i.is_numeric() {
return false;
}
}
return true;
}
fn contains_only_upper(iden: &str) -> bool {
for i in iden.chars() {
if !i.is_uppercase() && i != '_' && !i.is_numeric() {
return false;
}
}
return true;
}
Compiling solution v0.1.0 (file:///tmp/d20181108-22631-1vtw7s5/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.24s
     Running target/debug/deps/solution-7017bcc2d31a1134

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-773f144f21eb3f81

running 2 tests
test solution_test::test_invalid ... ok
test solution_test::test_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out
Димитър Луканов
  • Коректно
  • 2 успешни тест(а)
  • 0 неуспешни тест(а)
Димитър Луканов

use std::str::FromStr;
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyle {
Underscored,
Camelcased,
ScreamingSnakecased,
Unknown,
Mixed
}
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum CodeStyleError {
EmptyString,
InvalidFirstChar(char),
InvalidChar(char),
}
impl FromStr for CodeStyle {
type Err = CodeStyleError;
fn from_str(identifier: &str) -> Result<CodeStyle, CodeStyleError> {
fn identifier_code_style(mut iter:std::str::Chars,
mut style: CodeStyle,
mut error:Option<CodeStyleError>)
-> Result<CodeStyle, CodeStyleError> {
if !error.is_none() {
return Err(error.unwrap());
}
if iter.as_str() == "" {
return Ok(style);
}else{
let c = iter.next().unwrap();
if c == '_' {
if style == CodeStyle::Unknown {
style = CodeStyle::Underscored;
}else if style == CodeStyle::Camelcased {
style = CodeStyle::Mixed;
}
}else if char::is_alphabetic(c) {
if char::is_uppercase(c) {
if style == CodeStyle::Underscored {
style = CodeStyle::Mixed;
}else if style == CodeStyle::Unknown {
style = CodeStyle::Camelcased;
}
}else {
if style == CodeStyle::ScreamingSnakecased {
style = CodeStyle::Camelcased;
}
}
}else if !char::is_numeric(c){
error = Some(CodeStyleError::InvalidChar(c));
}
identifier_code_style(iter, style, error)
}
}
let trimmed_identifier = String::from(identifier.trim());
let mut char_iter = trimmed_identifier.chars();
let first_char:Option<char> = char_iter.next();
let mut code_style: CodeStyle = CodeStyle::Unknown;
let mut error: Option<CodeStyleError> = None;
if first_char.is_none() {
error = Some(CodeStyleError::EmptyString);
} else {
if !char::is_alphabetic(first_char.unwrap()) {
error = Some(CodeStyleError::InvalidFirstChar(first_char.unwrap()));
}
code_style = if char::is_uppercase(first_char.unwrap()) {
CodeStyle::ScreamingSnakecased
}else{
CodeStyle::Unknown
};
}
identifier_code_style(char_iter, code_style, error)
}
}
#[test]
fn is_valid() {
assert_eq!(CodeStyle::from_str("кирилицата").ok(), Some(CodeStyle::Unknown));
assert_eq!(CodeStyle::from_str("im").ok(), Some(CodeStyle::Unknown));
assert_eq!(CodeStyle::from_str(" so ").ok(), Some(CodeStyle::Unknown));
assert_eq!(CodeStyle::from_str("ti_red").ok(), Some(CodeStyle::Underscored));
assert_eq!(CodeStyle::from_str("of_Your").ok(), Some(CodeStyle::Mixed));
assert_eq!(CodeStyle::from_str("Shit").ok(), Some(CodeStyle::Camelcased));
assert_eq!(CodeStyle::from_str("GREG").ok(), Some(CodeStyle::ScreamingSnakecased));
}
#[test]
fn is_invalid() {
assert_eq!(CodeStyle::from_str("1MyMommaToldMe").err(), Some(CodeStyleError::InvalidFirstChar('1')));
assert_eq!(CodeStyle::from_str("I was").err(), Some(CodeStyleError::InvalidChar(' ')));
assert_eq!(CodeStyle::from_str("*special").err(), Some(CodeStyleError::InvalidFirstChar('*')));
assert_eq!(CodeStyle::from_str("").err(), Some(CodeStyleError::EmptyString));
}
Compiling solution v0.1.0 (file:///tmp/d20181108-22631-wo7ba4/solution)
    Finished dev [unoptimized + debuginfo] target(s) in 2.73s
     Running target/debug/deps/solution-7017bcc2d31a1134

running 2 tests
test is_invalid ... ok
test is_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

     Running target/debug/deps/solution_test-773f144f21eb3f81

running 2 tests
test solution_test::test_invalid ... ok
test solution_test::test_valid ... ok

test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out

   Doc-tests solution

running 0 tests

test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out