100 Exercises To Learn Rust - 4.14 Outro 풀기

문제

TODO: SaturatingU16 타입을 정의하세요.

  • u16 타입의 값을 가집니다.
  • u16, u8, &u16, &u8로부터 변환을 제공합니다.
  • SaturatingU16, u16, &u16, &SaturatingU16 타입의 right-hand side와 덧셈을 지원합니다.
  • u16의 최댓값에 도달하면 saturate되어야 합니다.
  • 다른 SaturatingU16 또는 u16과 비교할 수 있습니다.
  • 디버그 표현을 출력할 수 있습니다.

테스트 코드

#[test]
fn test_saturating_u16() {
    let a: SaturatingU16 = (&10u8).into();
    let b: SaturatingU16 = 5u8.into();
    let c: SaturatingU16 = u16::MAX.into();
    let d: SaturatingU16 = (&1u16).into();
    let e = &c;

    assert_eq!(a + b, SaturatingU16::from(15u16));
    assert_eq!(a + c, SaturatingU16::from(u16::MAX));
    assert_eq!(a + d, SaturatingU16::from(11u16));
    assert_eq!(a + a, 20u16);
    assert_eq!(a + 5u16, 15u16);
    assert_eq!(a + e, SaturatingU16::from(u16::MAX));
}

풀이

use std::ops::{Add,Deref};
#[derive(Debug, PartialEq, Copy, Clone)]
pub struct SaturatingU16 {
    value: u16,
}

impl SaturatingU16 {

}

// u16, u8, &u16, &u8로부터 변환을 제공
impl From<u16> for SaturatingU16 {
    fn from(value: u16) -> Self {
        SaturatingU16 { value }
    }
}

impl From<u8> for SaturatingU16 {
    fn from(value: u8) -> Self {
        SaturatingU16 { value: value as u16 }
    }
}

impl From<&u16> for SaturatingU16 {
    fn from(value: &u16) -> Self {
        SaturatingU16 { value: *value }
    }
}

impl From<&u8> for SaturatingU16 {
    fn from(value: &u8) -> Self {
        SaturatingU16 { value: *value as u16 }
    }
}

// SaturatingU16, u16, &u16, &SaturatingU16 타입의
// right-hand side와 덧셈을 지원
impl Add for SaturatingU16 {
    type Output = SaturatingU16;
    fn add(self, rhs: Self) -> Self::Output {
        SaturatingU16 { value: self.value.saturating_add(rhs.value) }
    }
}

impl Add<u16> for SaturatingU16 {
    type Output = SaturatingU16;
    fn add(self, rhs: u16) -> Self::Output {
        SaturatingU16 { value: self.value.saturating_add(rhs) }
    }
}

impl Add<&u16> for SaturatingU16 {
    type Output = SaturatingU16;
    fn add(self, rhs: &u16) -> Self::Output {
        SaturatingU16 { value: self.value.saturating_add(*rhs) }
    }
}

impl Add<&SaturatingU16> for SaturatingU16 {
    type Output = SaturatingU16;
    fn add(self, rhs: &SaturatingU16) -> Self::Output {
        SaturatingU16 { value: self.value.saturating_add(rhs.value) }
    }
}

// 다른 SaturatingU16 또는 u16과 비교

impl PartialEq<u16> for SaturatingU16 {
    fn eq(&self, other: &u16) -> bool {
        self.value == *other
    }
}

 

1. u16, u8, &u16, &u8로부터 타입 변환이 가능해야 한다.

 

각각의 타입마다 SaturatingU16 타입으로의 From 트레이트를 구현하여 타입 변환을 가능하도록 한다.

 

2. SaturatingU16, u16, &u16, &SaturatingU16 타입의 right-hand side와 덧셈을 지원해야 한다 + u16의 최댓값에 도달하면 saturate되어야 한다.

 

마찬가지로 각각의 타입마다 SaturatingU16 타입과의 Saturating_add 연산을 구현한다.

 

3. 다른 SaturatingU16 또는 u16과 비교할 수 있어야 한다.

 

자기 자신과 비교하기 위해 PartialEq 트레이트를 Derive로 구현하고, u16과의 비교는 PartialEq를 직접 구현한다.

 

 

+ 테스트에서 a + a와 같이 값을 계속 재활용하므로, CopyClone 트레이트를 구현한다.