Code Identifier

Предадени решения

Краен срок:
25.10.2018 17:00
Точки:
20

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

extern crate solution;
use solution::*;
#[test]
fn test_validity() {
assert!(CodeIdentifier::new("some-var").is_none());
assert!(CodeIdentifier::new("some var").is_none());
assert!(CodeIdentifier::new("+_+").is_none());
assert!(CodeIdentifier::new("❤️_❤️").is_none());
assert!(CodeIdentifier::new("123abc").is_none());
assert!(CodeIdentifier::new("a+b=c").is_none());
assert!(CodeIdentifier::new("abc123").is_some());
assert!(CodeIdentifier::new("some_var").is_some());
assert!(CodeIdentifier::new(" some_var ").is_some());
assert!(CodeIdentifier::new("someVar").is_some());
assert!(CodeIdentifier::new("SomeVar").is_some());
}
#[test]
fn test_both_static_and_dynamic_strings() {
assert!(CodeIdentifier::new("some_var").is_some());
let some_var = String::from("some_var");
assert!(CodeIdentifier::new(&some_var).is_some());
let some_var = "some_var";
assert!(CodeIdentifier::new(&some_var).is_some());
assert!(CodeIdentifier::new(&String::from("some_var")).is_some());
}
#[test]
fn test_camelcase_basic() {
let code_identifier = CodeIdentifier::new("some_var").unwrap();
assert_eq!(code_identifier.camelcase(), "someVar");
}
#[test]
fn test_underscore_basic() {
let code_identifier = CodeIdentifier::new("some_var").unwrap();
assert_eq!(code_identifier.underscore(), "some_var");
}
#[test]
fn test_screaming_snakecase_basic() {
let code_identifier = CodeIdentifier::new("some_var").unwrap();
assert_eq!(code_identifier.screaming_snakecase(), "SOME_VAR");
}
#[test]
fn test_titlecase_basic() {
let code_identifier = CodeIdentifier::new("some_var").unwrap();
assert_eq!(code_identifier.titlecase(), "SomeVar");
}
#[test]
fn test_kebabcase_basic() {
let code_identifier = CodeIdentifier::new("some_var").unwrap();
assert_eq!(code_identifier.kebabcase(), "some-var");
}
#[test]
fn test_normalize_case1() {
let code_identifier = CodeIdentifier::new("Some_Var").unwrap();
assert_eq!(code_identifier.underscore(), "some_var");
let code_identifier = CodeIdentifier::new("SomeVar").unwrap();
assert_eq!(code_identifier.underscore(), "somevar");
let code_identifier = CodeIdentifier::new("SOME_VAR").unwrap();
assert_eq!(code_identifier.underscore(), "some_var");
}
#[test]
fn test_normalize_case2() {
let code_identifier = CodeIdentifier::new("Some_Var").unwrap();
assert_eq!(code_identifier.camelcase(), "someVar");
let code_identifier = CodeIdentifier::new("SomeVar").unwrap();
assert_eq!(code_identifier.screaming_snakecase(), "SOMEVAR");
assert_eq!(code_identifier.camelcase(), "somevar");
let code_identifier = CodeIdentifier::new("SOME_VAR").unwrap();
assert_eq!(code_identifier.screaming_snakecase(), "SOME_VAR");
}
#[test]
fn test_cyrillic1() {
let code_identifier = CodeIdentifier::new("що_стана").unwrap();
assert_eq!(code_identifier.underscore(), "що_стана");
assert_eq!(code_identifier.screaming_snakecase(), "ЩО_СТАНА");
assert_eq!(code_identifier.camelcase(), "щоСтана");
assert_eq!(code_identifier.titlecase(), "ЩоСтана");
assert_eq!(code_identifier.kebabcase(), "що-стана");
}
#[test]
fn test_multibyte_uppercase() {
let code_identifier = CodeIdentifier::new("some_ßpecial_case").unwrap();
assert_eq!(code_identifier.camelcase(), "someSSpecialCase");
assert_eq!(code_identifier.screaming_snakecase(), "SOME_SSPECIAL_CASE");
}
#[test]
fn test_whitespace() {
let code_identifier = CodeIdentifier::new(" some_var\n").unwrap();
assert_eq!(code_identifier.underscore(), "some_var");
let code_identifier = CodeIdentifier::new("\tone_two_three ").unwrap();
assert_eq!(code_identifier.camelcase(), "oneTwoThree");
}
#[test]
fn test_digits1() {
let code_identifier = CodeIdentifier::new("some_var_123").unwrap();
assert_eq!(code_identifier.camelcase(), "someVar123");
assert_eq!(code_identifier.underscore(), "some_var_123");
let code_identifier = CodeIdentifier::new("some_123_var").unwrap();
assert_eq!(code_identifier.camelcase(), "some123Var");
assert_eq!(code_identifier.underscore(), "some_123_var");
}
#[test]
fn test_digits2() {
let code_identifier = CodeIdentifier::new("some_1_2_var").unwrap();
assert_eq!(code_identifier.camelcase(), "some12Var");
assert_eq!(code_identifier.underscore(), "some_1_2_var");
let code_identifier = CodeIdentifier::new("because_7_8_9").unwrap();
assert_eq!(code_identifier.camelcase(), "because789");
assert_eq!(code_identifier.underscore(), "because_7_8_9");
}
#[test]
fn test_digits3() {
let code_identifier = CodeIdentifier::new("some_٣_var").unwrap();
assert_eq!(code_identifier.camelcase(), "some٣Var");
assert_eq!(code_identifier.underscore(), "some_٣_var");
}

Задачата е да напишете тип, който "обвива" програмен идентификатор. Примерно, имена на променливи. Различните езици си имат различни стилове за идентификация, някои се очаква да са under_scored, някои ще са camelCased, тук-таме лиспаджиите kebab-case-ват неща. Ние ще очакваме да започнете от стандартния rust-ки стил за идентификатор: underscored, и да генерирате всички други. Примерно:

let code_identifier = CodeIdentifier::new("some_var").unwrap();

code_identifier.camelcase()  // => "someVar"
code_identifier.underscore() // => "some_var"

Забележете, че new функцията приема &str, но спокойно можете да си алокирате String от този &str чрез String::from и да боравите с него (или можете да си съхраните нещо друго? Както решите.)

Валидност

Очакваме да проверите, че подаденото наистина е валиден идентификатор, по следните правила:

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

Тоест, това са валидни идентификатори: some_var, abc1. Невалидни идентификатори са, например 1abc, @@@.

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

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

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

let code_identifier = CodeIdentifier::new(" some_var ");
let code_identifier = CodeIdentifier::new("some_var");

Ако ви подадем вход с разнообразен casing (големи/малки букви), нормализирайте го:

let code_identifier = CodeIdentifier::new("SoMe_vAr").unwrap();
code_identifier.underscore()          // => "some_var"
code_identifier.screaming_snakecase() // => "SOME_VAR"
code_identifier.camelcase()           // => "someVar"

Специални случаи

Случаи, за които (за нещастие) не сме се сетили, съответно няма да имаме тестове за тях:

  • Няколко _ символа един след друг
  • Символ _ в края на идентификатора

Можете да се справите с тези случаи както решите, или да ги игнорирате.


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

/// Необходимо е CodeIdentifier да имплементира Debug, за да можем да го
/// използваме в тестови assertion-и.
///
#[derive(Debug)]
pub struct CodeIdentifier {
    // Каквито полета ви трябват
}

impl CodeIdentifier {
    /// Функцията ще върне Option<CodeIdentifier>, което ще бъде:
    /// - None: ако входа не е валиден идентификатор. Вижте горе за това
    ///   какво значи "валиден идентификатор".
    /// - Some(code_identifier): Ако входа е валиден.
    ///
    pub fn new(identifier: &str) -> Option<Self> {
        unimplemented!()
    }

    /// Конвертира идентификатора до camelcased вариант.
    /// - Примерен вход: "some_var"
    /// - Примерен изход: "someVar"
    ///
    pub fn camelcase(&self) -> String {
        unimplemented!()
    }

    /// Конвертира идентификатора до titlecased вариант (camelcased с първа заглавна буква).
    /// - Примерен вход: "some_var"
    /// - Примерен изход: "SomeVar"
    ///
    pub fn titlecase(&self) -> String {
        unimplemented!()
    }

    /// Конвертира идентификатора до kebabcased вариант.
    /// - Примерен вход: "some_var"
    /// - Примерен изход: "some-var"
    ///
    pub fn kebabcase(&self) -> String {
        unimplemented!()
    }

    /// Конвертира идентификатора до underscored вариант.
    /// - Примерен вход: "some_var"
    /// - Примерен изход: "some_var"
    ///
    /// - Примерен вход: "Some_Var"
    /// - Примерен изход: "some_var"
    ///
    pub fn underscore(&self) -> String {
        unimplemented!()
    }

    /// Конвертира идентификатора до screaming-snakecased вариант.
    /// - Примерен вход: "some_var"
    /// - Примерен изход: "SOME_VAR"
    ///
    pub fn screaming_snakecase(&self) -> String {
        unimplemented!()
    }
}

Внимавайте всички типове и методи, които ни трябват, да бъдат маркирани като pub, за да могат тестовете ни да ги викат. Прочетете и общия guide за писане на домашни.

Задължително прочетете (или си припомнете): Указания за предаване на домашни