diff --git a/CHANGELOG.md b/CHANGELOG.md index 6f98a35..1d49f3b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,27 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). --- +## [1.0.0] — 2026-04-23 + +### Breaking + +- `ValueObject` trait split into two traits: `ValueObject` (construction + destructuring) and `PrimitiveValue` (single-primitive accessor via `.value()`). Types backed by a primitive implement both; composite types implement only `ValueObject`. +- Removed the `sql` feature and all SQLx integration. Database mapping is now the responsibility of the application layer (see the ORM guide in `docs/`). + +### Added + +- `PrimitiveValue` trait with a `.value() -> &Primitive` accessor for types whose canonical form is a single primitive. +- `TryFrom` and `TryFrom<&str>` implemented for all value objects — ergonomic construction without calling `::new()` explicitly. +- Serde deserialization now runs the full validation pipeline; deserializing an invalid value returns an error instead of producing an invalid object. +- Minimum `serde` version pinned to `1.0.116` (required for the `try_from` container attribute). + +### Fixed + +- Replaced `once_cell::sync::Lazy` with `std::sync::LazyLock` (stable since Rust 1.80); `once_cell` dependency removed. +- Stale `test-sql` CI job removed; `once_cell` removed from the `contact` feature declaration. + +--- + ## [0.1.1] — 2026-04-17 ### Added @@ -39,5 +60,7 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - `full` meta-feature - `prelude` module with convenience re-exports -[Unreleased]: https://github.com/codegress-com/arvo/compare/v0.1.0...HEAD +[Unreleased]: https://github.com/codegress-com/arvo/compare/v1.0.0...HEAD +[1.0.0]: https://github.com/codegress-com/arvo/compare/v0.1.1...v1.0.0 +[0.1.1]: https://github.com/codegress-com/arvo/compare/v0.1.0...v0.1.1 [0.1.0]: https://github.com/codegress-com/arvo/releases/tag/v0.1.0 diff --git a/Cargo.lock b/Cargo.lock index 44e8cd3..a5a3f2c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -45,7 +45,7 @@ checksum = "7c02d123df017efcdfbd739ef81735b36c5ba83ec3c59c80a9d7ecc718f92e50" [[package]] name = "arvo" -version = "0.9.0" +version = "1.0.0" dependencies = [ "base64", "chrono", diff --git a/Cargo.toml b/Cargo.toml index 9a46e4a..6ae3c20 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "arvo" -version = "0.9.0" +version = "1.0.0" license = "MIT" description = "Validated, immutable value objects for common domain types (email, money, identifiers, …)" authors = ["Codegress "] diff --git a/README.md b/README.md index 2ff1051..1ad61a8 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ Enable only the modules you need — unused features add zero dependencies. | Feature | What you get | Extra deps | |:---|:---|:---| -| `contact` | `EmailAddress`, `CountryCode`, `PhoneNumber`, `PostalAddress`, `Website` | `once_cell`, `regex`, `url` | +| `contact` | `EmailAddress`, `CountryCode`, `PhoneNumber`, `PostalAddress`, `Website` | `regex`, `url` | | `finance` | `Money`, `CurrencyCode`, `Iban`, `Bic`, `VatNumber`, `Percentage`, `ExchangeRate`, `CreditCardNumber`, `CardExpiryDate` | `rust_decimal`, `chrono` | | `geo` | `Latitude`, `Longitude`, `Coordinate`, `BoundingBox`, `TimeZone`, `CountryRegion` | — | | `measurement` | `Length`, `Weight`, `Temperature`, `Volume`, `Area`, `Speed`, `Pressure`, `Energy`, `Power`, `Frequency` | — | diff --git a/docs/contact.md b/docs/contact.md index 6f6c9c6..79c1859 100644 --- a/docs/contact.md +++ b/docs/contact.md @@ -4,7 +4,7 @@ Feature flag: `contact` ```toml [dependencies] -arvo = { version = "0.9", features = ["contact"] } +arvo = { version = "1.0", features = ["contact"] } ``` --- @@ -18,7 +18,7 @@ A validated, normalised email address. ```rust,ignore use arvo::contact::EmailAddress; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let email = EmailAddress::new("User@Example.COM".into())?; assert_eq!(email.value(), "user@example.com"); @@ -56,7 +56,7 @@ A validated ISO 3166-1 alpha-2 country code. ```rust,ignore use arvo::contact::CountryCode; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let code = CountryCode::new("cz".into())?; assert_eq!(code.value(), "CZ"); @@ -91,7 +91,7 @@ A validated phone number stored in canonical E.164 format. ```rust,ignore use arvo::contact::{CountryCode, PhoneNumber, PhoneNumberInput}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let phone = PhoneNumber::new(PhoneNumberInput { country_code: CountryCode::new("CZ".into())?, @@ -145,7 +145,7 @@ A validated website URL. Accepts `http` and `https` schemes only. Scheme and hos ```rust,ignore use arvo::contact::Website; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let site = Website::new("https://EXAMPLE.COM/path".into())?; assert_eq!(site.value(), "https://example.com/path"); @@ -184,7 +184,7 @@ A validated composite postal address. All text fields are trimmed; empty or whit ```rust,ignore use arvo::contact::{CountryCode, PostalAddress, PostalAddressInput}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let addr = PostalAddress::new(PostalAddressInput { street: "Václavské náměstí 1".into(), diff --git a/docs/finance.md b/docs/finance.md index 6313290..efbb56e 100644 --- a/docs/finance.md +++ b/docs/finance.md @@ -4,7 +4,7 @@ Feature flag: `finance` ```toml [dependencies] -arvo = { version = "0.9", features = ["finance"] } +arvo = { version = "1.0", features = ["finance"] } ``` --- @@ -18,7 +18,7 @@ A validated ISO 4217 alphabetic currency code. ```rust,ignore use arvo::finance::CurrencyCode; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let code = CurrencyCode::new("eur".into())?; assert_eq!(code.value(), "EUR"); @@ -54,7 +54,7 @@ A validated monetary amount with an associated currency. ```rust,ignore use arvo::finance::{CurrencyCode, Money, MoneyInput}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let money = Money::new(MoneyInput { amount: "10.50".parse()?, @@ -94,7 +94,7 @@ A validated IBAN (International Bank Account Number) using the mod-97 algorithm. ```rust,ignore use arvo::finance::Iban; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let iban = Iban::new("GB82 WEST 1234 5698 7654 32".into())?; assert_eq!(iban.value(), "GB82WEST12345698765432"); @@ -133,7 +133,7 @@ A validated BIC (Bank Identifier Code / SWIFT code). ```rust,ignore use arvo::finance::Bic; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let bic = Bic::new("DEUTDEDB".into())?; assert_eq!(bic.bank_code(), "DEUT"); @@ -166,7 +166,7 @@ A validated EU VAT number. ```rust,ignore use arvo::finance::VatNumber; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let vat = VatNumber::new("CZ 1234 5678".into())?; assert_eq!(vat.value(), "CZ12345678"); @@ -192,7 +192,7 @@ A validated percentage in the range `0.0..=100.0`. ```rust,ignore use arvo::finance::Percentage; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let p = Percentage::new(42.5)?; assert_eq!(*p.value(), 42.5); @@ -220,7 +220,7 @@ A validated currency exchange rate between two different currencies. ```rust,ignore use arvo::finance::{CurrencyCode, ExchangeRate, ExchangeRateInput}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let rate = ExchangeRate::new(ExchangeRateInput { from: CurrencyCode::new("EUR".into())?, @@ -259,7 +259,7 @@ A validated credit card number using the Luhn algorithm. ```rust,ignore use arvo::finance::CreditCardNumber; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let card = CreditCardNumber::new("4532 0151 1283 0366".into())?; assert_eq!(card.last_four(), "0366"); @@ -288,7 +288,7 @@ A validated credit/debit card expiry date that is not in the past. ```rust,ignore use arvo::finance::CardExpiryDate; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let exp = CardExpiryDate::new("12/28".into())?; assert_eq!(exp.value(), "12/28"); diff --git a/docs/geo.md b/docs/geo.md index 212ccd2..19a1d40 100644 --- a/docs/geo.md +++ b/docs/geo.md @@ -4,7 +4,7 @@ Feature flag: `geo` ```toml [dependencies] -arvo = { version = "0.9", features = ["geo"] } +arvo = { version = "1.0", features = ["geo"] } ``` --- @@ -17,7 +17,7 @@ A validated geographic latitude in decimal degrees. ```rust,ignore use arvo::geo::Latitude; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let lat = Latitude::new(48.8588)?; assert_eq!(*lat.value(), 48.8588); @@ -50,7 +50,7 @@ A validated geographic longitude in decimal degrees. ```rust,ignore use arvo::geo::Longitude; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let lng = Longitude::new(14.4208)?; assert_eq!(*lng.value(), 14.4208); @@ -82,7 +82,7 @@ A geographic coordinate (latitude + longitude pair). ```rust,ignore use arvo::geo::{Coordinate, CoordinateInput, Latitude, Longitude}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let coord = Coordinate::new(CoordinateInput { lat: Latitude::new(48.858844)?, @@ -122,7 +122,7 @@ A geographic bounding box defined by a south-west and a north-east [`Coordinate` ```rust,ignore use arvo::geo::{BoundingBox, BoundingBoxInput, Coordinate, CoordinateInput, Latitude, Longitude}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let sw = Coordinate::new(CoordinateInput { lat: Latitude::new(48.0)?, @@ -173,7 +173,7 @@ A validated IANA timezone name. ```rust,ignore use arvo::geo::TimeZone; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let tz = TimeZone::new("Europe/Prague".into())?; assert_eq!(tz.value(), "Europe/Prague"); @@ -210,7 +210,7 @@ A validated ISO 3166-2 subdivision code. ```rust,ignore use arvo::geo::CountryRegion; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let region = CountryRegion::new("cz-pr".into())?; assert_eq!(region.value(), "CZ-PR"); diff --git a/docs/identifiers.md b/docs/identifiers.md index f4513c7..83a8db8 100644 --- a/docs/identifiers.md +++ b/docs/identifiers.md @@ -4,7 +4,7 @@ Feature flag: `identifiers` ```toml [dependencies] -arvo = { version = "0.9", features = ["identifiers"] } +arvo = { version = "1.0", features = ["identifiers"] } ``` --- @@ -18,7 +18,7 @@ A URL-safe slug: lowercase alphanumeric characters and hyphens only. ```rust,ignore use arvo::identifiers::Slug; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let slug = Slug::new("Hello-World".into())?; assert_eq!(slug.value(), "hello-world"); @@ -56,7 +56,7 @@ A validated EAN-13 barcode number. ```rust,ignore use arvo::identifiers::Ean13; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let ean = Ean13::new("4006381333931".into())?; assert_eq!(ean.value(), "4006381333931"); @@ -89,7 +89,7 @@ A validated EAN-8 barcode number. ```rust,ignore use arvo::identifiers::Ean8; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let ean = Ean8::new("73513537".into())?; assert_eq!(ean.value(), "73513537"); @@ -122,7 +122,7 @@ A validated ISBN-13 number. ```rust,ignore use arvo::identifiers::Isbn13; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let isbn = Isbn13::new("978-0-306-40615-7".into())?; assert_eq!(isbn.value(), "9780306406157"); @@ -156,7 +156,7 @@ A validated ISBN-10 number. ```rust,ignore use arvo::identifiers::Isbn10; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let isbn = Isbn10::new("0-306-40615-2".into())?; assert_eq!(isbn.value(), "0306406152"); @@ -190,7 +190,7 @@ A validated ISSN (International Standard Serial Number). ```rust,ignore use arvo::identifiers::Issn; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let issn = Issn::new("0317-8471".into())?; assert_eq!(issn.value(), "0317-8471"); @@ -224,7 +224,7 @@ A validated Vehicle Identification Number (VIN) per ISO 3779. ```rust,ignore use arvo::identifiers::Vin; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let vin = Vin::new("1HGBH41JXMN109186".into())?; assert_eq!(vin.wmi(), "1HG"); diff --git a/docs/measurement.md b/docs/measurement.md index e3f4ac6..468e966 100644 --- a/docs/measurement.md +++ b/docs/measurement.md @@ -4,7 +4,7 @@ Feature flag: `measurement` ```toml [dependencies] -arvo = { version = "0.9", features = ["measurement"] } +arvo = { version = "1.0", features = ["measurement"] } ``` All measurement types share the same pattern: `XxxInput { value: f64, unit: XxxUnit }`. @@ -18,7 +18,7 @@ All measurement types share the same pattern: `XxxInput { value: f64, unit: XxxU ```rust,ignore use arvo::measurement::{Length, LengthInput, LengthUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let len = Length::new(LengthInput { value: 1.80, unit: LengthUnit::M })?; assert_eq!(len.value(), "1.8 m"); @@ -39,7 +39,7 @@ assert_eq!(len.amount(), 1.80); ```rust,ignore use arvo::measurement::{Weight, WeightInput, WeightUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let w = Weight::new(WeightInput { value: 75.0, unit: WeightUnit::Kg })?; assert_eq!(w.value(), "75 kg"); @@ -54,7 +54,7 @@ assert_eq!(w.value(), "75 kg"); ```rust,ignore use arvo::measurement::{Temperature, TemperatureInput, TemperatureUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let t = Temperature::new(TemperatureInput { value: 100.0, unit: TemperatureUnit::Celsius })?; assert_eq!(t.value(), "100 °C"); @@ -70,7 +70,7 @@ assert!(Temperature::new(TemperatureInput { value: -274.0, unit: TemperatureUnit ```rust,ignore use arvo::measurement::{Volume, VolumeInput, VolumeUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let v = Volume::new(VolumeInput { value: 1.5, unit: VolumeUnit::L })?; assert_eq!(v.value(), "1.5 l"); @@ -84,7 +84,7 @@ assert_eq!(v.value(), "1.5 l"); ```rust,ignore use arvo::measurement::{Area, AreaInput, AreaUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let a = Area::new(AreaInput { value: 50.0, unit: AreaUnit::M2 })?; assert_eq!(a.value(), "50 m²"); @@ -98,7 +98,7 @@ assert_eq!(a.value(), "50 m²"); ```rust,ignore use arvo::measurement::{Speed, SpeedInput, SpeedUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let s = Speed::new(SpeedInput { value: 120.0, unit: SpeedUnit::Kmh })?; assert_eq!(s.value(), "120 km/h"); @@ -112,7 +112,7 @@ assert_eq!(s.value(), "120 km/h"); ```rust,ignore use arvo::measurement::{Pressure, PressureInput, PressureUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let p = Pressure::new(PressureInput { value: 101.325, unit: PressureUnit::KPa })?; assert_eq!(p.value(), "101.325 kPa"); @@ -126,7 +126,7 @@ assert_eq!(p.value(), "101.325 kPa"); ```rust,ignore use arvo::measurement::{Energy, EnergyInput, EnergyUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let e = Energy::new(EnergyInput { value: 500.0, unit: EnergyUnit::Kcal })?; assert_eq!(e.value(), "500 kcal"); @@ -140,7 +140,7 @@ assert_eq!(e.value(), "500 kcal"); ```rust,ignore use arvo::measurement::{Power, PowerInput, PowerUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let p = Power::new(PowerInput { value: 3.7, unit: PowerUnit::KW })?; assert_eq!(p.value(), "3.7 kW"); @@ -154,7 +154,7 @@ assert_eq!(p.value(), "3.7 kW"); ```rust,ignore use arvo::measurement::{Frequency, FrequencyInput, FrequencyUnit}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let f = Frequency::new(FrequencyInput { value: 2.4, unit: FrequencyUnit::GHz })?; assert_eq!(f.value(), "2.4 GHz"); diff --git a/docs/net.md b/docs/net.md index e6479a2..37708c7 100644 --- a/docs/net.md +++ b/docs/net.md @@ -4,7 +4,7 @@ Feature flag: `net` ```toml [dependencies] -arvo = { version = "0.9", features = ["net"] } +arvo = { version = "1.0", features = ["net"] } ``` --- @@ -17,7 +17,7 @@ A validated URL. Accepts `http`, `https`, `ftp`, `ftps`, `ws`, and `wss` schemes ```rust,ignore use arvo::net::Url; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let url = Url::new("HTTPS://Example.COM/path".into())?; assert_eq!(url.value(), "https://example.com/path"); @@ -55,7 +55,7 @@ A validated domain name without a scheme (e.g. `"example.com"`). ```rust,ignore use arvo::net::Domain; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let domain = Domain::new("Example.COM".into())?; assert_eq!(domain.value(), "example.com"); @@ -86,7 +86,7 @@ A validated IPv4 address. Leading zeros in octets are rejected. ```rust,ignore use arvo::net::IpV4Address; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let ip = IpV4Address::new("192.168.1.1".into())?; assert_eq!(ip.value(), "192.168.1.1"); @@ -119,7 +119,7 @@ A validated IPv6 address, normalised to canonical compressed lowercase form. ```rust,ignore use arvo::net::IpV6Address; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let ip = IpV6Address::new("2001:0db8::0001".into())?; assert_eq!(ip.value(), "2001:db8::1"); @@ -149,7 +149,7 @@ A validated IP address — IPv4 or IPv6. Tries IPv4 first, then IPv6. ```rust,ignore use arvo::net::IpAddress; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let ip = IpAddress::new("192.168.1.1".into())?; assert!(ip.is_v4()); @@ -175,7 +175,7 @@ A validated network port number in the range `1..=65535`. Port 0 is reserved and ```rust,ignore use arvo::net::Port; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let port = Port::new(8080)?; assert_eq!(*port.value(), 8080); @@ -207,7 +207,7 @@ A validated MAC address, normalised to lowercase colon-separated hex. Accepts co ```rust,ignore use arvo::net::MacAddress; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let mac = MacAddress::new("AA:BB:CC:DD:EE:FF".into())?; assert_eq!(mac.value(), "aa:bb:cc:dd:ee:ff"); @@ -240,7 +240,7 @@ A validated MIME type. Trimmed and lowercased. Parameters (e.g. `; charset=utf-8 ```rust,ignore use arvo::net::MimeType; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let mime = MimeType::new("image/png".into())?; assert_eq!(mime.value(), "image/png"); @@ -276,7 +276,7 @@ A validated HTTP status code in the range `100..=599`. ```rust,ignore use arvo::net::HttpStatusCode; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let code = HttpStatusCode::new(200)?; assert!(code.is_success()); @@ -311,7 +311,7 @@ A validated API key — non-empty string. `Display` shows a masked form with onl ```rust,ignore use arvo::net::ApiKey; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let key = ApiKey::new("sk-1234567890abcd".into())?; assert_eq!(key.value(), "sk-1234567890abcd"); // full key diff --git a/docs/primitives.md b/docs/primitives.md index a1e6f7a..9797405 100644 --- a/docs/primitives.md +++ b/docs/primitives.md @@ -4,7 +4,7 @@ Feature flag: `primitives` ```toml [dependencies] -arvo = { version = "0.9", features = ["primitives"] } +arvo = { version = "1.0", features = ["primitives"] } ``` --- @@ -18,7 +18,7 @@ A non-empty, trimmed string. ```rust,ignore use arvo::primitives::NonEmptyString; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let s = NonEmptyString::new(" hello ".into())?; assert_eq!(s.value(), "hello"); @@ -51,7 +51,7 @@ A string whose length (in Unicode characters) is constrained at the type level. ```rust,ignore use arvo::primitives::BoundedString; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; type Username = BoundedString<3, 32>; @@ -86,7 +86,7 @@ A strictly positive integer (`i64 > 0`). ```rust,ignore use arvo::primitives::PositiveInt; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let n = PositiveInt::new(42)?; assert_eq!(*n.value(), 42); @@ -119,7 +119,7 @@ A non-negative integer (`i64 >= 0`). ```rust,ignore use arvo::primitives::NonNegativeInt; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let n = NonNegativeInt::new(0)?; assert_eq!(*n.value(), 0); @@ -151,7 +151,7 @@ A strictly positive decimal (`rust_decimal::Decimal > 0`). ```rust,ignore use arvo::primitives::PositiveDecimal; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; use rust_decimal::Decimal; use std::str::FromStr; @@ -184,7 +184,7 @@ A non-negative decimal (`rust_decimal::Decimal >= 0`). ```rust,ignore use arvo::primitives::NonNegativeDecimal; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; use rust_decimal::Decimal; let amount = NonNegativeDecimal::new(Decimal::ZERO)?; @@ -215,7 +215,7 @@ A probability value in the closed interval `[0.0, 1.0]`. ```rust,ignore use arvo::primitives::Probability; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let p = Probability::new(0.75)?; assert_eq!(*p.value(), 0.75); @@ -251,7 +251,7 @@ A CSS hex color in canonical `#RRGGBB` form. ```rust,ignore use arvo::primitives::HexColor; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let red = HexColor::new("#f00".into())?; assert_eq!(red.value(), "#FF0000"); @@ -293,7 +293,7 @@ A BCP 47 language tag (e.g. `"en-US"`, `"cs-CZ"`, `"fr"`). ```rust,ignore use arvo::primitives::Locale; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let locale = Locale::new("en_us".into())?; assert_eq!(locale.value(), "en-US"); @@ -331,7 +331,7 @@ A validated standard Base64-encoded string. ```rust,ignore use arvo::primitives::Base64String; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let b = Base64String::new("aGVsbG8=".into())?; assert_eq!(b.decode(), b"hello"); diff --git a/docs/temporal.md b/docs/temporal.md index f78b565..98669c8 100644 --- a/docs/temporal.md +++ b/docs/temporal.md @@ -4,7 +4,7 @@ Feature flag: `temporal` ```toml [dependencies] -arvo = { version = "0.9", features = ["temporal"] } +arvo = { version = "1.0", features = ["temporal"] } ``` --- @@ -18,7 +18,7 @@ A validated Unix timestamp — non-negative seconds since the Unix epoch (1970-0 ```rust,ignore use arvo::temporal::UnixTimestamp; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; let ts = UnixTimestamp::new(1_700_000_000).unwrap(); assert_eq!(*ts.value(), 1_700_000_000); @@ -45,7 +45,7 @@ A validated date of birth — strictly in the past and no more than 150 years ag ```rust,ignore use arvo::temporal::BirthDate; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; use chrono::NaiveDate; let dob = BirthDate::new(NaiveDate::from_ymd_opt(1990, 6, 15).unwrap()).unwrap(); @@ -80,7 +80,7 @@ A validated expiry date — strictly in the future at construction time. ```rust,ignore use arvo::temporal::ExpiryDate; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; use chrono::NaiveDate; let exp = ExpiryDate::new(NaiveDate::from_ymd_opt(2030, 12, 31).unwrap()).unwrap(); @@ -113,7 +113,7 @@ A validated time range — `start` must be strictly before `end`. ```rust,ignore use arvo::temporal::{TimeRange, TimeRangeInput}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; use chrono::{TimeZone, Utc}; let range = TimeRange::new(TimeRangeInput { @@ -153,7 +153,7 @@ Validated business hours for a single weekday — `open` must be strictly before ```rust,ignore use arvo::temporal::{BusinessHours, BusinessHoursInput}; -use arvo::traits::ValueObject; +use arvo::traits::{PrimitiveValue, ValueObject}; use chrono::{NaiveTime, Weekday}; let hours = BusinessHours::new(BusinessHoursInput {