tangle


git clone https://radroots.dev/git/tangle.git
Log | Files | Refs | README | LICENSE

commit 11a552fb6be730588bd2599d2e44547df6bdbeb7
parent 880e2fe9250d1bb96b3f0e6c19721797fb06c8c1
Author: triesap <tyson@radroots.org>
Date:   Fri,  5 Jun 2026 20:32:31 -0700

protocol: add event kind classification

Diffstat:
Mcrates/tangle_protocol/src/lib.rs | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------
1 file changed, 72 insertions(+), 6 deletions(-)

diff --git a/crates/tangle_protocol/src/lib.rs b/crates/tangle_protocol/src/lib.rs @@ -167,6 +167,39 @@ impl Kind { pub fn as_u32(self) -> u32 { self.0 } + + pub fn class(self) -> KindClass { + match self.0 { + 0 | 3 | 10_000..=19_999 => KindClass::Replaceable, + 20_000..=29_999 => KindClass::Ephemeral, + 30_000..=39_999 => KindClass::Addressable, + _ => KindClass::Regular, + } + } + + pub fn is_regular(self) -> bool { + self.class() == KindClass::Regular + } + + pub fn is_replaceable(self) -> bool { + self.class() == KindClass::Replaceable + } + + pub fn is_ephemeral(self) -> bool { + self.class() == KindClass::Ephemeral + } + + pub fn is_addressable(self) -> bool { + self.class() == KindClass::Addressable + } +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum KindClass { + Regular, + Replaceable, + Ephemeral, + Addressable, } impl fmt::Display for Kind { @@ -961,12 +994,12 @@ fn kind_out_of_range_error(value: u64) -> String { #[cfg(test)] mod tests { use super::{ - ClientMessage, Event, EventId, EventShapeError, Filter, Kind, PublicKeyHex, RawEventJson, - RelayMessage, SignatureHex, SubscriptionId, Tag, TagName, TagValue, UnixTimestamp, - UnsignedEvent, canonical_event_json, empty_error, encode_relay_message, event_from_value, - event_to_value, filter_from_value, invalid_length_error, kind_out_of_range_error, - non_lowercase_hex_error, parse_client_message, parse_event_json, relay_message_to_value, - too_long_error, + ClientMessage, Event, EventId, EventShapeError, Filter, Kind, KindClass, PublicKeyHex, + RawEventJson, RelayMessage, SignatureHex, SubscriptionId, Tag, TagName, TagValue, + UnixTimestamp, UnsignedEvent, canonical_event_json, empty_error, encode_relay_message, + event_from_value, event_to_value, filter_from_value, invalid_length_error, + kind_out_of_range_error, non_lowercase_hex_error, parse_client_message, parse_event_json, + relay_message_to_value, too_long_error, }; use core::str::FromStr; use std::collections::hash_map::DefaultHasher; @@ -1077,6 +1110,39 @@ mod tests { } #[test] + fn event_kind_classification_matches_nip01_ranges() { + for value in [1, 2, 4, 44, 1_000, 9_999, 45, 40_000] { + let kind = Kind::new(value).expect("regular"); + assert_eq!(kind.class(), KindClass::Regular); + assert!(kind.is_regular()); + assert!(!kind.is_replaceable()); + assert!(!kind.is_ephemeral()); + assert!(!kind.is_addressable()); + } + + for value in [0, 3, 10_000, 19_999] { + let kind = Kind::new(value).expect("replaceable"); + assert_eq!(kind.class(), KindClass::Replaceable); + assert!(kind.is_replaceable()); + } + + for value in [20_000, 29_999] { + let kind = Kind::new(value).expect("ephemeral"); + assert_eq!(kind.class(), KindClass::Ephemeral); + assert!(kind.is_ephemeral()); + } + + for value in [30_000, 39_999] { + let kind = Kind::new(value).expect("addressable"); + assert_eq!(kind.class(), KindClass::Addressable); + assert!(kind.is_addressable()); + } + + assert_eq!(format!("{:?}", KindClass::Regular), "Regular"); + assert_eq!(KindClass::Regular, KindClass::Regular); + } + + #[test] fn scalar_errors_have_stable_messages() { assert_eq!(empty_error("id"), "id must not be empty"); assert_eq!(