В общем для интереса решил описать структурку с огикой управления Semantic Version. Вот код:
use std::fmt;
use std::cmp;
use std::result::Result::{self, Ok, Err};
struct Version {
major: i64,
minor: i64,
patch: i64
}
impl Version {
fn new() -> Version {
Version{major: 0, minor: 0, patch: 0}
}
fn value(&self) -> String {
format!("{}.{}.{}", self.major, self.minor, self.patch)
}
fn inc_major(&self) -> Version {
Version{major: self.major + 1, minor: 0, patch: 0}
}
fn inc_minor(&self) -> Version {
Version{major: self.major, minor: self.minor + 1, patch: 0}
}
fn inc_patch(&self) -> Version {
Version{major: self.major, minor: self.minor, patch: self.patch + 1}
}
}
struct VersionBuilder(Version);
impl VersionBuilder {
fn new() -> VersionBuilder {
VersionBuilder(Version::new())
}
fn major(mut self, value: i64) -> VersionBuilder {
self.0.major = value;
self
}
fn minor(mut self, value: i64) -> VersionBuilder {
self.0.minor = value;
self
}
fn patch(mut self, value: i64) -> VersionBuilder {
self.0.patch = value;
self
}
fn finalize(self) -> 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::Eq for Version {}
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()
}
}
pub struct ParseVersionError { _priv: () }
impl fmt::Display for ParseVersionError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
"предоставленная строка должна содержать три подверсии разделенные \
точкой: `{major}.{minor}.{patch}`".fmt(f)
}
}
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)
}
}
fn main() {
let v1 = &VersionBuilder::new()
.major(2)
.patch(3);
v1.minor(11);
v1.minor(2);
v1.major(1);
let v2 = &Version{major: 1, minor: 2, patch:5}.inc_minor();
check_version(v1.finalize(), v2);
}
Сейчас при сборке он обсыпается на последней строчке, т.к. ожидает получить ссылку, а получает объект:
main.rs:161:19: 161:32 error: mismatched types:
expected `&Version`,
found `Version`
(expected &-ptr,
found struct `Version`) [E0308]
main.rs:161 check_version(v1.finalize(), v2);
Если же я ставлю перед v1 «&» v1.finalize()
, то получаю:
main.rs:153:5: 153:7 error: cannot move out of borrowed content
main.rs:153 v1.minor(11);
^~
main.rs:155:5: 155:7 error: cannot move out of borrowed content
main.rs:155 v1.minor(2);
^~
main.rs:157:5: 157:7 error: cannot move out of borrowed content
main.rs:157 v1.major(1);
^~
main.rs:161:20: 161:22 error: cannot move out of borrowed content
main.rs:161 check_version(&v1.finalize(), v2);
Я что-то запутался...
Как мне правильно разрулить здесь с ссылками и владением?
Может будут еще акие замечания?