Rust 如何确保我的函数将收到有效长度的Vec?

Rust 如何确保我的函数将收到有效长度的Vec?,rust,Rust,是否可以指定函数的Vec参数具有一定的长度?考虑骰子的可能价值: fn new(d_type: DiceType, face_vals: /*Vec<u32> with len() == 2/4/6/8/10/12/20*/) -> Dice {...} 回答 被接受的答案显示了返回值的结果的良好用途,但响应让我思考如何使代码更灵活,同时仍然有一个硬帽,可以保证单掷的溢出安全,因此我删掉了一堆代码,并提出了以下内容,这应该可以让你每掷1-10000个骰子使用倍增器进行额外掷骰

是否可以指定函数的
Vec
参数具有一定的长度?考虑骰子的可能价值:

fn new(d_type: DiceType, face_vals: /*Vec<u32> with len() == 2/4/6/8/10/12/20*/) -> Dice {...}
回答

被接受的答案显示了返回值的结果的良好用途,但响应让我思考如何使代码更灵活,同时仍然有一个硬帽,可以保证单掷的溢出安全,因此我删掉了一堆代码,并提出了以下内容,这应该可以让你每掷1-10000个骰子使用倍增器进行额外掷骰

const MAX_FACE_VALUE: u32 = 100000;
const MAX_FACE_COUNT: u32 = 10000;
const MAX_ROLL_COUNT: u32 = 9999;

pub struct Dice {
    face_count: usize,
    face_values: Vec<u32>,
}

impl Dice {
    pub fn new(mut face_vals: Vec<u32>) -> Self {
        //User may not have values greater than 100,000
        //Index access is safe since we use the for _ in _
        for x in 0..face_vals.len() {
            if face_vals[x] > MAX_FACE_VALUE {
                //Enforce the limit
                face_vals[x] = MAX_FACE_VALUE;
            }
        }

        //User may not have more than 10,000 faces
        if face_vals.len() > MAX_FACE_COUNT as usize {
            let new_vals: Vec<u32> = face_vals.split_off(MAX_FACE_COUNT as usize);
            Dice {
                face_count: MAX_FACE_COUNT as usize,
                face_values: new_vals,
            }
        } else if face_vals.len() == 0 {
            //No 0 sided dice allowed
            Dice {
                face_count: 1,
                face_values: vec![1],
            }
        } else {
            //Normal range
            Dice {
                face_count: face_vals.len(),
                face_values: face_vals,
            }
        }
    }
}
常数最大值:u32=100000;
const MAX_FACE_COUNT:u32=10000;
常量最大滚动计数:u32=9999;
pub结构骰子{
面部计数:使用,
面值:Vec,
}
插入骰子{
发布fn新(多个面:Vec)->Self{
//用户的值不能大于100000
//索引访问是安全的,因为我们在_
对于0..face_vals.len()中的x{
如果面值[x]>最大面值{
//执行限制
面值[x]=最大面值;
}
}
//用户不能有超过10000个面
如果face\u vals.len()>MAX\u face\u算作usize{
让新值:Vec=face\u vals.split\u off(MAX\u face\u计为usize);
掷骰子{
面部计数:使用时的最大面部计数,
面值:新值,
}
}如果face_vals.len()=0,则为else{
//不允许0边骰子
掷骰子{
人脸计数:1,
面_值:vec![1],
}
}否则{
//正常范围
掷骰子{
face_count:face_vals.len(),
面值:面值,
}
}
}
}

您应该使用
结果来解释可能的错误输入:

use std::cmp::Ordering;

#[derive(Clone, Copy)]
pub enum DiceType {
    D2,
    D4,
    D6,
    D8,
    D10,
    D10P,
    D12,
    D20
}

pub struct Dice {
    dice_type: DiceType,
    // no need for face_count, it's a method of DiceType
    face_values: Vec<u32>
}

// an error for invalid face value inputs
enum DiceError {
    TooFewFaceValues,
    TooManyFaceValues
}

impl DiceType {
    fn face_count(&self) -> usize {
        match self {
            DiceType::D2 => 2,
            DiceType::D4 => 4,
            _            => unimplemented!() // TODO: account for all the other variants
        }
    }
}

impl Dice {
    fn new(dice_type: DiceType, face_values: &[u32]) -> Result<Self, DiceError> {
        match face_values.len().cmp(&dice_type.face_count()) {
            Ordering::Less    => Err(DiceError::TooFewFaceValues),
            Ordering::Greater => Err(DiceError::TooManyFaceValues),
            Ordering::Equal   => Ok(
                Dice {
                    dice_type,
                    face_values: Vec::from(face_values)
                }
            )
        }
    }
}
使用std::cmp::排序;
#[派生(克隆、复制)]
发布枚举类型{
D2,
D4,
D6,
D8,
D10,
D10P,
D12,
D20
}
pub结构骰子{
骰子类型:骰子类型,
//不需要脸计数,这是一种骰子类型的方法
面值:Vec
}
//无效面值输入的错误
枚举骰子错误{
TooFewFaceValues,
TooManyFaceValues
}
简单骰子类型{
fn面部计数(&self)->使用{
匹配自我{
DiceType::D2=>2,
DiceType::D4=>4,
_=>未实现!()//TODO:说明所有其他变体
}
}
}
插入骰子{
fn新(骰子类型:骰子类型,面值:&[u32])->结果{
匹配面\u值.len().cmp(&dice\u type.face\u count()){
排序::Less=>Err(DiceError::ToofeFaceValues),
排序::更大=>Err(DiceError::TooManyFaceValues),
排序::相等=>Ok(
掷骰子{
骰子型,
面_值:Vec::from(面_值)
}
)
}
}
}

您应该使用
结果来解释可能的错误输入:

use std::cmp::Ordering;

#[derive(Clone, Copy)]
pub enum DiceType {
    D2,
    D4,
    D6,
    D8,
    D10,
    D10P,
    D12,
    D20
}

pub struct Dice {
    dice_type: DiceType,
    // no need for face_count, it's a method of DiceType
    face_values: Vec<u32>
}

// an error for invalid face value inputs
enum DiceError {
    TooFewFaceValues,
    TooManyFaceValues
}

impl DiceType {
    fn face_count(&self) -> usize {
        match self {
            DiceType::D2 => 2,
            DiceType::D4 => 4,
            _            => unimplemented!() // TODO: account for all the other variants
        }
    }
}

impl Dice {
    fn new(dice_type: DiceType, face_values: &[u32]) -> Result<Self, DiceError> {
        match face_values.len().cmp(&dice_type.face_count()) {
            Ordering::Less    => Err(DiceError::TooFewFaceValues),
            Ordering::Greater => Err(DiceError::TooManyFaceValues),
            Ordering::Equal   => Ok(
                Dice {
                    dice_type,
                    face_values: Vec::from(face_values)
                }
            )
        }
    }
}
使用std::cmp::排序;
#[派生(克隆、复制)]
发布枚举类型{
D2,
D4,
D6,
D8,
D10,
D10P,
D12,
D20
}
pub结构骰子{
骰子类型:骰子类型,
//不需要脸计数,这是一种骰子类型的方法
面值:Vec
}
//无效面值输入的错误
枚举骰子错误{
TooFewFaceValues,
TooManyFaceValues
}
简单骰子类型{
fn面部计数(&self)->使用{
匹配自我{
DiceType::D2=>2,
DiceType::D4=>4,
_=>未实现!()//TODO:说明所有其他变体
}
}
}
插入骰子{
fn新(骰子类型:骰子类型,面值:&[u32])->结果{
匹配面\u值.len().cmp(&dice\u type.face\u count()){
排序::Less=>Err(DiceError::ToofeFaceValues),
排序::更大=>Err(DiceError::TooManyFaceValues),
排序::相等=>Ok(
掷骰子{
骰子型,
面_值:Vec::from(面_值)
}
)
}
}
}

您应该使用具有固定长度对应数组的变体的枚举:

#[derive(Clone, Copy)]
pub enum Dice {
    D2([u32; 2]),
    D4([u32; 4]),
    D6([u32; 6]),
    D8([u32; 8]),
    D10([u32; 10]),
    D10P([u32; 10]),
    D12([u32; 12]),
    D20([u32; 20]),
}
则不能有无效值:

fn take_a_dice(_dice: Dice) {
    //
}

fn main() {
    take_a_dice(Dice::D4([1, 2, 4, 8]));
}

应使用具有固定长度对应数组的变体的枚举:

#[derive(Clone, Copy)]
pub enum Dice {
    D2([u32; 2]),
    D4([u32; 4]),
    D6([u32; 6]),
    D8([u32; 8]),
    D10([u32; 10]),
    D10P([u32; 10]),
    D12([u32; 12]),
    D20([u32; 20]),
}
则不能有无效值:

fn take_a_dice(_dice: Dice) {
    //
}

fn main() {
    take_a_dice(Dice::D4([1, 2, 4, 8]));
}

也许将骰子包装成一个结果,这样我就可以返回有效的骰子或错误?注意,您不需要retval变量。只要把
if
/
else
的东西放进去:
if我的{Dice{…}else{Dice{…}
请不要在你的问题里放答案。欢迎您回答下面的问题,甚至接受这个答案。这更好,因为它允许社区对其他答案和这些答案进行投票。也许可以将骰子包装在结果中,以便我可以返回有效的骰子或错误?请注意,您不需要retval变量。只要把
if
/
else
的东西放进去:
if我的{Dice{…}else{Dice{…}
请不要在你的问题里放答案。欢迎您回答下面的问题,甚至接受这个答案。这是更好的,因为它允许更多的答案和那些答案由社区投票。其想法是用户应该能够为脸提供自定义值。所以我想要一个有“[1,20,40,60]”的d4,它应该能够支持这个。您的代码会给出“[1,2,3,4]”。我会将错误更改为类似于
struct DiceError{expected:usize,actual:usize}
这样的想法是用户应该能够为面提供自定义值。所以我想要一个有“[1,20,40,60]”的d4,它应该能够支持这个。您的代码将给出“[1,2,3,4]”。我会将错误更改为类似于
struct DiceError{expected:usize,actual:usize}
N