#[derive(ValueObject)]
{
// Attributes available to this derive:
#[value_object]
}
Expand description
English:
Implements ddd_toolkit_core::ValueObject and value-based
Debug, Clone, PartialEq, Eq, and Hash, with corresponding field bounds.
Accepts nonempty named or tuple structs and nonempty enums, not unions or unit
structs. A single-field struct exposes that field as Inner, as_inner, and
into_inner; multi-field structs and enums use Self instead. Structs get
new with fields in declaration order. Multi-field structs also get borrowed
accessors named after fields, or field_0, field_1, etc. for tuple fields.
Enums get new_<variant>, is_<variant>, and as_<variant>, using the fully
lowercased variant name (not snake case). Variant accessors return None for
another variant, Some(()) for unit variants, or a tuple of field references.
Lowercased variant names must be distinct; generated names must not collide
with other methods or field accessors.
#[value_object(trait_only)] generates only the domain trait implementation,
with the same Inner mapping but no inherent methods, constructors, standard
traits, or extra bounds. It preserves handwritten APIs and cannot be combined
with validate, error, or serde. It does not enforce invariants on public
fields, direct enum construction, or independently implemented deserialization.
#[value_object(validate = path, error = ErrorType)] replaces new with
try_new (or try_new_<variant>). Both options are required together. The
validator receives &Inner for a single-field struct and &Self otherwise,
returns Result<(), ErrorType>, and runs before the constructor returns the
value. Its error is propagated; its panics are not caught. Validated struct
fields cannot be unrestricted pub. Restricted visibility, direct construction
inside the defining module, and enum variants can still bypass validation.
#[value_object(serde)] additionally generates serialization through the core
crate’s serde re-export; enable the core crate’s serde feature. Single-field
structs serialize as their inner value, named structs as structs, tuple structs
as tuples, and enums as externally tagged variants. Single-field tuple variants
use Serde’s newtype format; other tuple variants use tuple format.
Deserialization runs validation when configured,
mapping its errors to value object validation failed. Serialization generation
is selected by this attribute, not by a feature on the macro crate.
Invalid shapes, duplicate or unknown options, and missing core dependencies
produce compile errors; field types must satisfy the generated trait bounds.
日本語:
ddd_toolkit_core::ValueObject と値に基づく Debug、Clone、
PartialEq、Eq、Hash を、各フィールドに必要な境界付きで実装します。
空でない名前付き・タプル構造体と列挙型に対応し、共用体やユニット構造体は拒否します。
単一フィールド構造体の Inner、as_inner、into_inner はそのフィールドを扱い、
複数フィールド構造体と列挙型では Self を扱います。構造体には宣言順の引数を取る
new を生成します。複数フィールドの場合は名前付きフィールド名、またはタプルの
field_0、field_1 などの名前で借用アクセサーも生成します。
列挙型にはバリアント名をすべて小文字にした(snake case ではない)接尾辞で
new_<variant>、is_<variant>、as_<variant> を生成します。
バリアントアクセサーは不一致なら None、ユニットなら Some(())、それ以外は
フィールド参照のタプルを返します。小文字化した名前は一意である必要があり、
生成する名前を他のメソッドやフィールドアクセサーと衝突させないでください。
#[value_object(trait_only)] は同じ Inner 対応のドメイントレイト実装だけを
生成し、固有メソッド、コンストラクター、標準トレイト、追加の境界は生成しません。
手書きの API を維持でき、validate、error、serde とは併用できません。
公開フィールド、列挙型の直接構築、別途実装された逆直列化の不変条件は保証しません。
#[value_object(validate = path, error = ErrorType)] は new を try_new
(列挙型では try_new_<variant>)に置き換えます。両オプションの同時指定が必要です。
検証関数は単一フィールドなら &Inner、それ以外なら &Self を受け取り、
Result<(), ErrorType> を返します。値を返す前に検証し、エラーを伝播します。
検証関数のパニックは捕捉しません。検証付き構造体のフィールドは無制限の pub に
できませんが、制限付き公開、定義モジュール内の直接構築、列挙型のバリアントからは
検証を迂回できます。
#[value_object(serde)] はコアの serde 再公開を使う直列化実装も生成します。
コアの serde feature を有効にしてください。単一フィールドは内包値、名前付き
構造体は構造体、タプル構造体はタプル、列挙型は外部タグ形式で直列化します。
単一フィールドのタプルバリアントは Serde の newtype 形式、その他はタプル形式です。
逆直列化時も設定された検証を
実行し、検証エラーを value object validation failed に変換します。
直列化の生成はマクロクレートの feature ではなく、この属性で選択します。
非対応の形状、重複・未知のオプション、コア依存の欠落はコンパイルエラーになります。
フィールド型は生成するトレイトの境界を満たす必要があります。
§Example / 使用例
use ddd_toolkit_macro::ValueObject;
#[derive(ValueObject)]
#[value_object(validate = positive, error = &'static str)]
struct Quantity(u32);
fn positive(value: &u32) -> Result<(), &'static str> {
if *value > 0 { Ok(()) } else { Err("zero quantity") }
}
assert_eq!(Quantity::try_new(0), Err("zero quantity"));
assert_eq!(Quantity::try_new(2).unwrap().into_inner(), 2);
#[derive(ValueObject)]
enum Status { Pending, Ready(u32) }
let status = Status::new_ready(7);
assert_eq!(status.as_ready(), Some((&7,)));
assert!(!status.is_pending());