LINUX.ORG.RU

Разбить один исходник на несколько в rust

 ,


0

3

В одной из тем был накидан такой исходник. Решил его разбить на несколько файлов.
Получилось два файла: semver.rs и main.rs. Тупо вынес всю логику semver в отдельный файл, ничего не меняя.
Добавил в начало main.rs mod semver;. Запускаю:

   Compiling vers v0.1.0 (file:///home/deterok/data/projects/vers)
semver.rs:63:6: 63:23 error: failed to resolve. Use of undeclared type or module `std::fmt`
semver.rs:63 impl std::fmt::Display for Version {
                  ^~~~~~~~~~~~~~~~~
semver.rs:63:6: 63:23 error: use of undeclared trait name `std::fmt::Display`
semver.rs:63 impl std::fmt::Display for Version {
                  ^~~~~~~~~~~~~~~~~
semver.rs:103:6: 103:23 error: failed to resolve. Use of undeclared type or module `std::str`
semver.rs:103 impl std::str::FromStr for Version {
                   ^~~~~~~~~~~~~~~~~
semver.rs:103:6: 103:23 error: use of undeclared trait name `std::str::FromStr`
semver.rs:103 impl std::str::FromStr for Version {
                   ^~~~~~~~~~~~~~~~~
semver.rs:131:6: 131:23 error: failed to resolve. Use of undeclared type or module `std::fmt`
semver.rs:131 impl std::fmt::Display for ParseVersionError {
                   ^~~~~~~~~~~~~~~~~
semver.rs:131:6: 131:23 error: use of undeclared trait name `std::fmt::Display`
semver.rs:131 impl std::fmt::Display for ParseVersionError {
                   ^~~~~~~~~~~~~~~~~
main.rs:8:23: 8:30 error: use of undeclared type name `Version`
main.rs:8 fn check_version(v1: &Version, v2: &Version) {
                                ^~~~~~~
main.rs:8:37: 8:44 error: use of undeclared type name `Version`
main.rs:8 fn check_version(v1: &Version, v2: &Version) {
                                              ^~~~~~~
main.rs:17:18: 17:37 error: failed to resolve. Use of undeclared type or module `VersionBuilder`
main.rs:17     let mut v1 = VersionBuilder::new();
                            ^~~~~~~~~~~~~~~~~~~
main.rs:17:18: 17:37 error: unresolved name `VersionBuilder::new`
main.rs:17     let mut v1 = VersionBuilder::new();
                            ^~~~~~~~~~~~~~~~~~~
main.rs:22:14: 22:21 error: `Version` does not name a structure
main.rs:22     let v2 = Version{major: 1, minor: 2, patch:5}.inc_minor();
                        ^~~~~~~
main.rs:27:30: 27:37 error: use of undeclared type name `Version`
main.rs:27     match v2.value().parse::<Version>() {
                                        ^~~~~~~
error: aborting due to 12 previous errors
Could not compile `vers`.

Ага! Надо добавить use semver::*; в main.rs. Собираю:

cargo run
   Compiling vers v0.1.0 (file:///home/deterok/data/projects/vers)
semver.rs:63:6: 63:23 error: failed to resolve. Use of undeclared type or module `std::fmt`
semver.rs:63 impl std::fmt::Display for Version {
                  ^~~~~~~~~~~~~~~~~
semver.rs:63:6: 63:23 error: use of undeclared trait name `std::fmt::Display`
semver.rs:63 impl std::fmt::Display for Version {
                  ^~~~~~~~~~~~~~~~~
semver.rs:103:6: 103:23 error: failed to resolve. Use of undeclared type or module `std::str`
semver.rs:103 impl std::str::FromStr for Version {
                   ^~~~~~~~~~~~~~~~~
semver.rs:103:6: 103:23 error: use of undeclared trait name `std::str::FromStr`
semver.rs:103 impl std::str::FromStr for Version {
                   ^~~~~~~~~~~~~~~~~
semver.rs:131:6: 131:23 error: failed to resolve. Use of undeclared type or module `std::fmt`
semver.rs:131 impl std::fmt::Display for ParseVersionError {
                   ^~~~~~~~~~~~~~~~~
semver.rs:131:6: 131:23 error: use of undeclared trait name `std::fmt::Display`
semver.rs:131 impl std::fmt::Display for ParseVersionError {
                   ^~~~~~~~~~~~~~~~~
main.rs:9:23: 9:30 error: use of undeclared type name `Version`
main.rs:9 fn check_version(v1: &Version, v2: &Version) {
                                ^~~~~~~
main.rs:9:37: 9:44 error: use of undeclared type name `Version`
main.rs:9 fn check_version(v1: &Version, v2: &Version) {
                                              ^~~~~~~
main.rs:18:18: 18:37 error: failed to resolve. Use of undeclared type or module `VersionBuilder`
main.rs:18     let mut v1 = VersionBuilder::new();
                            ^~~~~~~~~~~~~~~~~~~
main.rs:18:18: 18:37 error: unresolved name `VersionBuilder::new`
main.rs:18     let mut v1 = VersionBuilder::new();
                            ^~~~~~~~~~~~~~~~~~~
main.rs:23:14: 23:21 error: `Version` does not name a structure
main.rs:23     let v2 = Version{major: 1, minor: 2, patch:5}.inc_minor();
                        ^~~~~~~
main.rs:28:30: 28:37 error: use of undeclared type name `Version`
main.rs:28     match v2.value().parse::<Version>() {
                                        ^~~~~~~
error: aborting due to 12 previous errors
Could not compile `vers`.

Как правильно это сделать?

★★★★★
semver.rs:63 impl std::fmt::Display for Version {
                  ^~~~~~~~~~~~~~~~~

«std::fmt» в "::std::fmt" или «fmt».

main.rs:18     let mut v1 = VersionBuilder::new();
                            ^~~~~~~~~~~~~~~~~~~

Перед «struct» и каждой функцией impl (кроме типажей) необходимо проставить «pub», тем самым расширяя область видимости за пределы файла. Далее в main'е идет обращение напрямую к полям структуры «Version»: каждому полю по «pub»у. Дополнительная информация: тут и 6 страниц тут. Весь код:

mod semver;
use semver::*;

fn main() {
    let mut v1 = VersionBuilder::new();

    v1.major(1).minor(2);
    v1.patch(3);

    let v2 = Version{major: 1, minor: 2, patch:5}.inc_minor();

    check_version(&v1.finalize(), &v2);

    // match "3.4..ы.5".parse::<Version>() { // Проверка ошибки
    match "3.4.5".parse::<Version>() {
        Ok(v)    => println!("{}", v),
        Err(err) => println!("Error: {}", err)
    }
}
use std::fmt;
use std::cmp;
use std::result::Result::{self, Ok, Err};


#[derive(Eq)]
pub struct Version {
    pub major: i64,
    pub minor: i64,
    pub patch: i64
}

impl Version {
    pub fn new() -> Version {
        Version{major: 0, minor: 0, patch: 0}
    }

    pub fn value(&self) -> String {
        format!("{}.{}.{}", self.major, self.minor, self.patch)
    }

    pub fn inc_major(&self) -> Version {
        Version{major: self.major + 1, minor: 0, patch: 0}
    }

    pub fn inc_minor(&self) -> Version {
        Version{major: self.major, minor: self.minor + 1, patch: 0}
    }

    pub fn inc_patch(&self) -> Version {
        Version{major: self.major, minor: self.minor, patch: self.patch + 1}
    }
}

pub struct VersionBuilder(Version);


impl VersionBuilder {
    pub fn new() -> VersionBuilder {
        VersionBuilder(Version::new())
    }

    pub fn major(&mut self, value: i64) -> &mut VersionBuilder {
        self.0.major = value;
        self
    }

    pub fn minor(&mut self, value: i64) -> &mut VersionBuilder {
        self.0.minor = value;
        self
    }

    pub fn patch(&mut self, value: i64) -> &mut VersionBuilder {
        self.0.patch = value;
        self
    }

    pub fn finalize(&self) -> Version {
        Version{.. self.0}
    }
}

impl ::std::fmt::Display for Version {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Version({})", self.value())
    }
}


impl cmp::PartialEq for Version {
    fn eq(&self, other: &Self) -> bool{
        if (self.major == other.major) &&
            (self.minor == other.minor) &&
            (self.patch == other.patch) {
                return true
            }

        false
    }
}

impl cmp::PartialOrd for Version {
    fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> {
        match self.major.cmp(&other.major) {
            cmp::Ordering::Greater => return Some(cmp::Ordering::Greater),
            cmp::Ordering::Less    => return Some(cmp::Ordering::Less),
            cmp::Ordering::Equal   =>
                match self.minor.cmp(&other.minor) {
                    cmp::Ordering::Greater => return Some(cmp::Ordering::Greater),
                    cmp::Ordering::Less    => return Some(cmp::Ordering::Less),
                    cmp::Ordering::Equal   => return Some(self.patch.cmp(&other.patch))
            }
        }
    }
}

impl cmp::Ord for Version {
    fn cmp(&self, other: &Self) -> cmp::Ordering{
        self.partial_cmp(other).unwrap()
    }
}

impl ::std::str::FromStr for Version {
    type Err = ParseVersionError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {

        let splitted: Vec<&str> = s.split('.').collect();
        let count = splitted.len();


        if count != 3 {
            return Err(ParseVersionError{_priv: ()})
        }

        let major = splitted[0].parse::<i64>().unwrap();
        let minor = splitted[1].parse::<i64>().unwrap();
        let patch = splitted[2].parse::<i64>().unwrap();

        let v = Version{
            major: major,
            minor: minor,
            patch: patch};

        Ok(v)
    }
}

pub struct ParseVersionError { _priv: () }

impl ::std::fmt::Display for ParseVersionError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        "provided string must contain three subversions separated by a dot.\n\
         For example: \"1.2.3\".".fmt(f)
    }
}

pub fn check_version(v1: &Version, v2: &Version) {
    match v1.cmp(v2) {
        cmp::Ordering::Greater => println!("{} больше {}", v1, v2),
        cmp::Ordering::Less    => println!("{} меньше {}", v1, v2),
        cmp::Ordering::Equal   => println!("Версии равны: {}", v1)
    }
}
shaiZaigh
()
Ответ на: комментарий от shaiZaigh

Супер, спасибо!

Пара вопросов есть:
1) Какие есть еще способы определить пустую структуру типа этой pub struct ParseVersionError { _priv: () }?
2) Может можно как-то импортировать всем элементы модуля как public?

deterok ★★★★★
() автор топика
Последнее исправление: deterok (всего исправлений: 1)
Ответ на: комментарий от deterok

1) Какие есть еще способы определить пустую структуру типа этой pub struct ParseVersionError { _priv: () }?

Вот так в смысле? Или о чём речь?

struct Empty;

DarkEld3r ★★★★★
()
Ответ на: комментарий от deterok

1. Как сказали чуть выше - можно создать юнит структуру без полей, к методам которой можно обращаться напрямую.

struct Empty;
impl Empty {
    fn abc(&self) -> bool {
        true
    }
}
fn main() {
    println!("{}", Empty.abc());
}
2. В начало файла main.rs добавить:
include!("semver.rs");

shaiZaigh
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.