#values #present #group #optional #multiple-values

someval

包含至少一个存在的可选值组的集合

1个不稳定版本

0.1.0 2023年5月8日

#19 in #present

MIT许可证

10KB
130

包含至少一个存在的可选值组的集合

动机

有时应用程序需要确保至少有一个值存在,同时允许存在多个不同类型的值。在这种情况下,一个常见的模式是跟踪多个Option值,并要求至少有一个包含值。

/// Represent distinct optional values for a couple of types:
struct NameId {
    id: Option<u64>,
    name: Option<String>,
}

impl NameId {
    fn ensure_value_is_present(&self) -> Result<(), &'static str> {
        if self.id.is_some() || self.name.is_some() {
            Ok(())
        } else {
            Err("either an id or a name or both must be present")
        }
    }
}

let good_value = NameId { id: Some(42), name: None };
assert!(good_value.ensure_value_is_present().is_ok());

let bad_value = NameId { id: None, name: None };
assert!(bad_value.ensure_value_is_present().is_err());

概述

此crate提供类型来表示此模式。

有时应用程序需要表示1个或多个可能具有不同类型的值。这就是someval进入“使非法状态不可表示”此模式的地方。

“someval”是一种类似于Option值集合的类型,但它保证在类型检查时,运行时始终至少有一个值存在。

“someval”类型

此crate中的“someval”类型遵循常见的结构,它们支持泛型的数量不同。它们都命名为SomeN,后缀N表示可能的值的数量,例如[Some2]、[Some3]等。所以[Some2]是两个类型泛型:Some2<A, B>,而[Some3]是三个:Some3<A, B, C>等。

每个“someval”类型都是一个枚举。类型参数和枚举变体都使用大写英文字母作为占位符,例如。

use someval::Some2;

type NameId = Some2<u64, String>;

let nid = NameId::A(42);

对于每个存在的值的组合,都有一个枚举变体。

use someval::Some3;

type Triple = Some3<i64, &'static str, bool>;

let val = Triple::AC(42, false);

构建“somevals”

可以使用枚举变体构建值。

use someval::Some2;

type NameId = Some2<u64, String>;

let nid1 = NameId::A(42);
let nid2 = NameId::B("Alice".to_string());
let nid3 = NameId::AB(13, "Bob".to_string());

可以使用From将具有所有类型存在的值从值元组转换为。

let nid4 = NameId::from((13, "Bob".to_string()));
assert_eq!(nid3, nid4);

可以使用TryFrom将值从Option值元组可错误地转换为。

let res1 = NameId::try_from((Some(42), None));
assert!(res1.is_ok());
let res2 = NameId::try_from((None, None));
assert!(res2.is_err());

类似于[Some2]的“someval”可以始终转换为Option值元组。


type NameId = Some2<u64, String>;

let nid = NameId::A(42);
let (optid, optname) = nid.into();
assert_eq!(optid, Some(42));
assert_eq!(optname, None);

大多数“someval”方法使用复制/移动接收器,并提供一个as_ref方法将它们转换为引用(类似于Option::as_refResult::as_ref,不要与AsRef::as_ref混淆)。


type NameId = Some2<u64, String>;

let nid = NameId::A(42);
let idref: &u64 = match nid.as_ref() {
    Some2::A(x) => x,
    _ => panic!(),
};
assert_eq!(*idref, 42);

单个访问器方法为组件提供Option(类似于Result::okResult::err)。


type NameId = Some2<u64, String>;

let nid = NameId::A(42);
assert_eq!(nid.as_ref().a(), Some(&42));
assert_eq!(nid.as_ref().b(), None);

无运行时依赖项