电商网站设计岗位主要是,swipe类网站,适合负债者的10个副业,珠海市手机网站建设品牌这段代码定义了一个泛型结构体 LengthT, Unit#xff0c;用于表示一维长度#xff0c;其中 T 表示长度的数值类型#xff0c;而 Unit 是一个编译时检查单位一致性的占位符类型#xff0c;不会用于运行时表示长度的值。这个设计允许开发者在编译阶段确保不同单位之间…这段代码定义了一个泛型结构体 LengthT, Unit用于表示一维长度其中 T 表示长度的数值类型而 Unit 是一个编译时检查单位一致性的占位符类型不会用于运行时表示长度的值。这个设计允许开发者在编译阶段确保不同单位之间的长度值在使用前进行了显式的单位转换。
一、length.rs文件源码
//! 用计量单位标记的一维长度。use crate::approxeq::ApproxEq;
use crate::approxord::{max, min};
use crate::num::Zero;
use crate::scale::Scale;use crate::num::One;
#[cfg(feature bytemuck)]
use bytemuck::{Pod, Zeroable};
use core::cmp::Ordering;
use core::fmt;
use core::hash::{Hash, Hasher};
use core::iter::Sum;
use core::marker::PhantomData;
use core::ops::{Add, Div, Mul, Neg, Sub};
use core::ops::{AddAssign, DivAssign, MulAssign, SubAssign};
use num_traits::{NumCast, Saturating};
#[cfg(feature serde)]
use serde::{Deserialize, Deserializer, Serialize, Serializer};/*
一维距离其值由“T”表示测量单位为“Unit”。
“T”可以是任何数字类型例如像“u64”或“f32”这样的基元类型。
“Unit”不用于表示“Length”值。它仅在编译时使用以确保用一个单位存储的“Length”在用于需要不同单位的表达式之前被显式转换。它可能是一个没有值的类型例如空枚举。
您可以将“Length”乘以“Scale”将其从一个单位转换为另一个单位。请参阅[Scale]结构体。
*/
#[repr(C)]
pub struct LengthT, Unit(pub T, #[doc(hidden)] pub PhantomDataUnit);implT: Clone, U Clone for LengthT, U {fn clone(self) - Self {Length(self.0.clone(), PhantomData)}
}implT: Copy, U Copy for LengthT, U {}#[cfg(feature serde)]
implde, T, U Deserializede for LengthT, U where T: Deserializede,{fn deserializeD(deserializer: D) - ResultSelf, D::Error where D: Deserializerde,{Ok(Length(Deserialize::deserialize(deserializer)?, PhantomData))}
}#[cfg(feature serde)]
implT, U Serialize for LengthT, U where T: Serialize,{fn serializeS(self, serializer: S) - ResultS::Ok, S::Error where S: Serializer,{self.0.serialize(serializer)}
}#[cfg(feature arbitrary)]
impla, T, U arbitrary::Arbitrarya for LengthT, U
whereT: arbitrary::Arbitrarya,
{fn arbitrary(u: mut arbitrary::Unstructureda) - arbitrary::ResultSelf {Ok(Length(arbitrary::Arbitrary::arbitrary(u)?, PhantomData))}
}#[cfg(feature bytemuck)]
unsafe implT: Zeroable, U Zeroable for LengthT, U {}#[cfg(feature bytemuck)]
unsafe implT: Pod, U: static Pod for LengthT, U {}implT, U LengthT, U {/// 将值与度量单位相关联。#[inline]pub const fn new(x: T) - Self {Length(x, PhantomData)}
}implT: Clone, U LengthT, U {/// 从类中提取基值pub fn get(self) - T {self.0}/// Cast the unit#[inline]pub fn cast_unitV(self) - LengthT, V {Length::new(self.0)}/// Linearly interpolate between this length and another length.////// # Example////// rust/// use euclid::default::Length;////// let from Length::new(0.0);/// let to Length::new(8.0);////// assert_eq!(from.lerp(to, -1.0), Length::new(-8.0));/// assert_eq!(from.lerp(to, 0.0), Length::new( 0.0));/// assert_eq!(from.lerp(to, 0.5), Length::new( 4.0));/// assert_eq!(from.lerp(to, 1.0), Length::new( 8.0));/// assert_eq!(from.lerp(to, 2.0), Length::new(16.0));/// #[inline]pub fn lerp(self, other: Self, t: T) - SelfwhereT: One SubOutput T MulOutput T AddOutput T,{let one_t T::one() - t.clone();Length::new(one_t * self.0.clone() t * other.0)}
}implT: PartialOrd, U LengthT, U {/// Returns minimum between this length and another length.#[inline]pub fn min(self, other: Self) - Self {min(self, other)}/// Returns maximum between this length and another length.#[inline]pub fn max(self, other: Self) - Self {max(self, other)}
}implT: NumCast Clone, U LengthT, U {/// Cast from one numeric representation to another, preserving the units.#[inline]pub fn castNewT: NumCast(self) - LengthNewT, U {self.try_cast().unwrap()}/// Fallible cast from one numeric representation to another, preserving the units.pub fn try_castNewT: NumCast(self) - OptionLengthNewT, U {NumCast::from(self.0).map(Length::new)}
}implT: fmt::Debug, U fmt::Debug for LengthT, U {fn fmt(self, f: mut fmt::Formatter) - fmt::Result {self.0.fmt(f)}
}implT: Default, U Default for LengthT, U {#[inline]fn default() - Self {Length::new(Default::default())}
}implT: Hash, U Hash for LengthT, U {fn hashH: Hasher(self, h: mut H) {self.0.hash(h);}
}// length length
implT: Add, U Add for LengthT, U {type Output LengthT::Output, U;fn add(self, other: Self) - Self::Output {Length::new(self.0 other.0)}
}// length length
implT: Add Copy, U AddSelf for LengthT, U {type Output LengthT::Output, U;fn add(self, other: Self) - Self::Output {Length::new(self.0 other.0)}
}// length_iter.copied().sum()
implT: AddOutput T Zero, U Sum for LengthT, U {fn sumI: IteratorItem Self(iter: I) - Self {iter.fold(Self::zero(), Add::add)}
}// length_iter.sum()
impla, T: a AddOutput T Copy Zero, U: a Suma Self for LengthT, U {fn sumI: IteratorItem a Self(iter: I) - Self {iter.fold(Self::zero(), Add::add)}
}// length length
implT: AddAssign, U AddAssign for LengthT, U {fn add_assign(mut self, other: Self) {self.0 other.0;}
}// length - length
implT: Sub, U Sub for LengthT, U {type Output LengthT::Output, U;fn sub(self, other: LengthT, U) - Self::Output {Length::new(self.0 - other.0)}
}// length - length
implT: SubAssign, U SubAssign for LengthT, U {fn sub_assign(mut self, other: Self) {self.0 - other.0;}
}// Saturating length length and length - length.
implT: Saturating, U Saturating for LengthT, U {fn saturating_add(self, other: Self) - Self {Length::new(self.0.saturating_add(other.0))}fn saturating_sub(self, other: Self) - Self {Length::new(self.0.saturating_sub(other.0))}
}// length / length
implSrc, Dst, T: Div DivLengthT, Src for LengthT, Dst {type Output ScaleT::Output, Src, Dst;#[inline]fn div(self, other: LengthT, Src) - Self::Output {Scale::new(self.0 / other.0)}
}// length * scalar
implT: Mul, U MulT for LengthT, U {type Output LengthT::Output, U;#[inline]fn mul(self, scale: T) - Self::Output {Length::new(self.0 * scale)}
}// length * scalar
implT: Copy MulT, Output T, U MulAssignT for LengthT, U {#[inline]fn mul_assign(mut self, scale: T) {*self *self * scale;}
}// length / scalar
implT: Div, U DivT for LengthT, U {type Output LengthT::Output, U;#[inline]fn div(self, scale: T) - Self::Output {Length::new(self.0 / scale)}
}// length / scalar
implT: Copy DivT, Output T, U DivAssignT for LengthT, U {#[inline]fn div_assign(mut self, scale: T) {*self *self / scale;}
}// length * scaleFactor
implSrc, Dst, T: Mul MulScaleT, Src, Dst for LengthT, Src {type Output LengthT::Output, Dst;#[inline]fn mul(self, scale: ScaleT, Src, Dst) - Self::Output {Length::new(self.0 * scale.0)}
}// length / scaleFactor
implSrc, Dst, T: Div DivScaleT, Src, Dst for LengthT, Dst {type Output LengthT::Output, Src;#[inline]fn div(self, scale: ScaleT, Src, Dst) - Self::Output {Length::new(self.0 / scale.0)}
}// -length
implU, T: Neg Neg for LengthT, U {type Output LengthT::Output, U;#[inline]fn neg(self) - Self::Output {Length::new(-self.0)}
}implT: PartialEq, U PartialEq for LengthT, U {fn eq(self, other: Self) - bool {self.0.eq(other.0)}
}implT: PartialOrd, U PartialOrd for LengthT, U {fn partial_cmp(self, other: Self) - OptionOrdering {self.0.partial_cmp(other.0)}
}implT: Eq, U Eq for LengthT, U {}implT: Ord, U Ord for LengthT, U {fn cmp(self, other: Self) - Ordering {self.0.cmp(other.0)}
}implT: Zero, U Zero for LengthT, U {#[inline]fn zero() - Self {Length::new(Zero::zero())}
}implU, T: ApproxEqT ApproxEqT for LengthT, U {#[inline]fn approx_epsilon() - T {T::approx_epsilon()}#[inline]fn approx_eq_eps(self, other: LengthT, U, approx_epsilon: T) - bool {self.0.approx_eq_eps(other.0, approx_epsilon)}
}#[cfg(test)]
mod tests {use super::Length;use crate::num::Zero;use crate::scale::Scale;use core::f32::INFINITY;use num_traits::Saturating;enum Inch {}enum Mm {}enum Cm {}enum Second {}#[cfg(feature serde)]mod serde {use super::*;extern crate serde_test;use self::serde_test::assert_tokens;use self::serde_test::Token;#[test]fn test_length_serde() {let one_cm: Lengthf32, Mm Length::new(10.0);assert_tokens(one_cm, [Token::F32(10.0)]);}}#[test]fn test_clone() {// A cloned Length is a separate length with the state matching the// original Length at the point it was cloned.let mut variable_length: Lengthf32, Inch Length::new(12.0);let one_foot variable_length.clone();variable_length.0 24.0;assert_eq!(one_foot.get(), 12.0);assert_eq!(variable_length.get(), 24.0);}#[test]fn test_add() {let length1: Lengthu8, Mm Length::new(250);let length2: Lengthu8, Mm Length::new(5);assert_eq!((length1 length2).get(), 255);assert_eq!((length1 length2).get(), 255);}#[test]fn test_sum() {type L Lengthf32, Mm;let lengths [L::new(1.0), L::new(2.0), L::new(3.0)];assert_eq!(lengths.iter().sum::L(), L::new(6.0));}#[test]fn test_addassign() {let one_cm: Lengthf32, Mm Length::new(10.0);let mut measurement: Lengthf32, Mm Length::new(5.0);measurement one_cm;assert_eq!(measurement.get(), 15.0);}#[test]fn test_sub() {let length1: Lengthu8, Mm Length::new(250);let length2: Lengthu8, Mm Length::new(5);let result length1 - length2;assert_eq!(result.get(), 245);}#[test]fn test_subassign() {let one_cm: Lengthf32, Mm Length::new(10.0);let mut measurement: Lengthf32, Mm Length::new(5.0);measurement - one_cm;assert_eq!(measurement.get(), -5.0);}#[test]fn test_saturating_add() {let length1: Lengthu8, Mm Length::new(250);let length2: Lengthu8, Mm Length::new(6);let result length1.saturating_add(length2);assert_eq!(result.get(), 255);}#[test]fn test_saturating_sub() {let length1: Lengthu8, Mm Length::new(5);let length2: Lengthu8, Mm Length::new(10);let result length1.saturating_sub(length2);assert_eq!(result.get(), 0);}#[test]fn test_division_by_length() {// Division results in a Scale from denominator units// to numerator units.let length: Lengthf32, Cm Length::new(5.0);let duration: Lengthf32, Second Length::new(10.0);let result length / duration;let expected: Scalef32, Second, Cm Scale::new(0.5);assert_eq!(result, expected);}#[test]fn test_multiplication() {let length_mm: Lengthf32, Mm Length::new(10.0);let cm_per_mm: Scalef32, Mm, Cm Scale::new(0.1);let result length_mm * cm_per_mm;let expected: Lengthf32, Cm Length::new(1.0);assert_eq!(result, expected);}#[test]fn test_multiplication_with_scalar() {let length_mm: Lengthf32, Mm Length::new(10.0);let result length_mm * 2.0;let expected: Lengthf32, Mm Length::new(20.0);assert_eq!(result, expected);}#[test]fn test_multiplication_assignment() {let mut length: Lengthf32, Mm Length::new(10.0);length * 2.0;let expected: Lengthf32, Mm Length::new(20.0);assert_eq!(length, expected);}#[test]fn test_division_by_scalefactor() {let length: Lengthf32, Cm Length::new(5.0);let cm_per_second: Scalef32, Second, Cm Scale::new(10.0);let result length / cm_per_second;let expected: Lengthf32, Second Length::new(0.5);assert_eq!(result, expected);}#[test]fn test_division_by_scalar() {let length: Lengthf32, Cm Length::new(5.0);let result length / 2.0;let expected: Lengthf32, Cm Length::new(2.5);assert_eq!(result, expected);}#[test]fn test_division_assignment() {let mut length: Lengthf32, Mm Length::new(10.0);length / 2.0;let expected: Lengthf32, Mm Length::new(5.0);assert_eq!(length, expected);}#[test]fn test_negation() {let length: Lengthf32, Cm Length::new(5.0);let result -length;let expected: Lengthf32, Cm Length::new(-5.0);assert_eq!(result, expected);}#[test]fn test_cast() {let length_as_i32: Lengthi32, Cm Length::new(5);let result: Lengthf32, Cm length_as_i32.cast();let length_as_f32: Lengthf32, Cm Length::new(5.0);assert_eq!(result, length_as_f32);}#[test]fn test_equality() {let length_5_point_0: Lengthf32, Cm Length::new(5.0);let length_5_point_1: Lengthf32, Cm Length::new(5.1);let length_0_point_1: Lengthf32, Cm Length::new(0.1);assert!(length_5_point_0 length_5_point_1 - length_0_point_1);assert!(length_5_point_0 ! length_5_point_1);}#[test]fn test_order() {let length_5_point_0: Lengthf32, Cm Length::new(5.0);let length_5_point_1: Lengthf32, Cm Length::new(5.1);let length_0_point_1: Lengthf32, Cm Length::new(0.1);assert!(length_5_point_0 length_5_point_1);assert!(length_5_point_0 length_5_point_1);assert!(length_5_point_0 length_5_point_1 - length_0_point_1);assert!(length_5_point_1 length_5_point_0);assert!(length_5_point_1 length_5_point_0);assert!(length_5_point_0 length_5_point_1 - length_0_point_1);}#[test]fn test_zero_add() {type LengthCm Lengthf32, Cm;let length: LengthCm Length::new(5.0);let result length - LengthCm::zero();assert_eq!(result, length);}#[test]fn test_zero_division() {type LengthCm Lengthf32, Cm;let length: LengthCm Length::new(5.0);let length_zero: LengthCm Length::zero();let result length / length_zero;let expected: Scalef32, Cm, Cm Scale::new(INFINITY);assert_eq!(result, expected);}
}二、结构体定义
#[repr(C)]
pub struct LengthT, Unit(pub T, #[doc(hidden)] pub PhantomDataUnit);#[repr©]保证结构体在内存中的布局与C语言兼容通常用于确保与C/C代码或外部接口的二进制兼容性。PhantomData一个零大小的类型用于在编译时携带类型信息而不会增加结构体的大小。这里用于确保单位的一致性。
三、实现Clone
implT: Clone, U Clone for LengthT, U {fn clone(self) - Self {Length(self.0.clone(), PhantomData)}
}这段代码实现了Clone trait允许Length类型的值被克隆。PhantomData的实例化应使用PhantomData::而不是直接使用PhantomData虽然Rust编译器通常可以推断。
四、cast和try_cast方法
implT: NumCast Clone, U LengthT, U {/// Cast from one numeric representation to another, preserving the units.#[inline]pub fn castNewT: NumCast(self) - LengthNewT, U {self.try_cast().unwrap()}/// Fallible cast from one numeric representation to another, preserving the units.pub fn try_castNewT: NumCast(self) - OptionLengthNewT, U {NumCast::from(self.0).map(Length::new)}
}这里我们使用了num_traits::NumCast trait来实现数值类型之间的转换。cast方法调用try_cast并解包Option这意味着如果转换失败程序将会panic。try_cast方法尝试将Length的数值部分从类型T转换为NewT如果成功则使用新的数值和原始的单位类型U创建一个新的Length值。
五、其他trait实现
fmt::Debug为Length实现Debug trait使得Length值可以格式化输出。Default为Length实现Default trait允许使用default()方法创建默认值的Length实例。Hash为Length实现Hash trait使得Length值可以被哈希。Length Length 的加法Length Length 的加法Length 迭代器的求和Sum实现针对可复制的情况Length 迭代器的求和Sum实现Length Length 的加法减法实现比较特性PartialEq, PartialOrd, Eq, Ord的实现零值特性Zero的实现近似相等特性ApproxEq的实现 #六、结束语 这个结构体不仅提供了数值和单位的泛型表示还通过实现各种 trait 来支持丰富的操作如加减、克隆、比较和哈希等。这使得 LengthT, U 能够与 Rust 标准库中的许多算法和数据结构无缝协作同时保持了泛型性和类型安全。