···117117 Data::from_json(&json).map(|data| data.into_static())
118118 }
119119120120+ /// Get as object if this is an Object variant
121121+ pub fn as_object(&self) -> Option<&Object<'s>> {
122122+ if let Data::Object(obj) = self {
123123+ Some(obj)
124124+ } else {
125125+ None
126126+ }
127127+ }
128128+129129+ /// Get as array if this is an Array variant
130130+ pub fn as_array(&self) -> Option<&Array<'s>> {
131131+ if let Data::Array(arr) = self {
132132+ Some(arr)
133133+ } else {
134134+ None
135135+ }
136136+ }
137137+138138+ /// Get as string if this is a String variant
139139+ pub fn as_str(&self) -> Option<&str> {
140140+ if let Data::String(s) = self {
141141+ Some(s.as_str())
142142+ } else {
143143+ None
144144+ }
145145+ }
146146+147147+ /// Get as integer if this is an Integer variant
148148+ pub fn as_integer(&self) -> Option<i64> {
149149+ if let Data::Integer(i) = self {
150150+ Some(*i)
151151+ } else {
152152+ None
153153+ }
154154+ }
155155+156156+ /// Get as boolean if this is a Boolean variant
157157+ pub fn as_boolean(&self) -> Option<bool> {
158158+ if let Data::Boolean(b) = self {
159159+ Some(*b)
160160+ } else {
161161+ None
162162+ }
163163+ }
164164+165165+ /// Check if this is a null value
166166+ pub fn is_null(&self) -> bool {
167167+ matches!(self, Data::Null)
168168+ }
169169+170170+ /// Serialize to canonical DAG-CBOR bytes for CID computation
171171+ ///
172172+ /// This produces the deterministic CBOR encoding used for content-addressing.
173173+ pub fn to_dag_cbor(
174174+ &self,
175175+ ) -> Result<Vec<u8>, serde_ipld_dagcbor::EncodeError<std::collections::TryReserveError>> {
176176+ serde_ipld_dagcbor::to_vec(self)
177177+ }
178178+120179 /// Parse a Data value from an IPLD value (CBOR)
121180 pub fn from_cbor(cbor: &'s Ipld) -> Result<Self, AtDataError> {
122181 Ok(match cbor {
···358417}
359418360419impl<'d> RawData<'d> {
420420+ /// Get as object if this is an Object variant
421421+ pub fn as_object(&self) -> Option<&BTreeMap<SmolStr, RawData<'d>>> {
422422+ if let RawData::Object(obj) = self {
423423+ Some(obj)
424424+ } else {
425425+ None
426426+ }
427427+ }
428428+429429+ /// Get as array if this is an Array variant
430430+ pub fn as_array(&self) -> Option<&Vec<RawData<'d>>> {
431431+ if let RawData::Array(arr) = self {
432432+ Some(arr)
433433+ } else {
434434+ None
435435+ }
436436+ }
437437+438438+ /// Get as string if this is a String variant
439439+ pub fn as_str(&self) -> Option<&str> {
440440+ if let RawData::String(s) = self {
441441+ Some(s.as_ref())
442442+ } else {
443443+ None
444444+ }
445445+ }
446446+447447+ /// Get as boolean if this is a Boolean variant
448448+ pub fn as_boolean(&self) -> Option<bool> {
449449+ if let RawData::Boolean(b) = self {
450450+ Some(*b)
451451+ } else {
452452+ None
453453+ }
454454+ }
455455+456456+ /// Check if this is a null value
457457+ pub fn is_null(&self) -> bool {
458458+ matches!(self, RawData::Null)
459459+ }
460460+461461+ /// Serialize to canonical DAG-CBOR bytes for CID computation
462462+ ///
463463+ /// This produces the deterministic CBOR encoding used for content-addressing.
464464+ pub fn to_dag_cbor(
465465+ &self,
466466+ ) -> Result<Vec<u8>, serde_ipld_dagcbor::EncodeError<std::collections::TryReserveError>> {
467467+ serde_ipld_dagcbor::to_vec(self)
468468+ }
469469+361470 /// Convert a CBOR-encoded byte slice into a `RawData` value.
362471 /// Parse a Data value from an IPLD value (CBOR)
363472 pub fn from_cbor(cbor: &'d Ipld) -> Result<Self, AtDataError> {
+117
crates/jacquard-common/src/types/value/tests.rs
···813813 assert_eq!(result.text, "null test");
814814 assert_eq!(result.langs, None);
815815}
816816+817817+#[test]
818818+fn test_data_accessors() {
819819+ // Test as_object
820820+ let mut map = BTreeMap::new();
821821+ map.insert(SmolStr::new_static("key"), Data::Integer(42));
822822+ let obj_data = Data::Object(Object(map.clone()));
823823+ assert!(obj_data.as_object().is_some());
824824+ assert_eq!(obj_data.as_object().unwrap().0.len(), 1);
825825+ assert!(Data::Null.as_object().is_none());
826826+827827+ // Test as_array
828828+ let arr_data = Data::Array(Array(vec![Data::Integer(1), Data::Integer(2)]));
829829+ assert!(arr_data.as_array().is_some());
830830+ assert_eq!(arr_data.as_array().unwrap().0.len(), 2);
831831+ assert!(Data::Null.as_array().is_none());
832832+833833+ // Test as_str
834834+ let str_data = Data::String(AtprotoStr::String("hello".into()));
835835+ assert_eq!(str_data.as_str(), Some("hello"));
836836+ assert!(Data::Null.as_str().is_none());
837837+838838+ // Test as_integer
839839+ let int_data = Data::Integer(42);
840840+ assert_eq!(int_data.as_integer(), Some(42));
841841+ assert!(Data::Null.as_integer().is_none());
842842+843843+ // Test as_boolean
844844+ let bool_data = Data::Boolean(true);
845845+ assert_eq!(bool_data.as_boolean(), Some(true));
846846+ assert!(Data::Null.as_boolean().is_none());
847847+848848+ // Test is_null
849849+ assert!(Data::Null.is_null());
850850+ assert!(!Data::Integer(0).is_null());
851851+}
852852+853853+#[test]
854854+fn test_rawdata_accessors() {
855855+ // Test as_object
856856+ let mut map = BTreeMap::new();
857857+ map.insert(SmolStr::new_static("key"), RawData::SignedInt(42));
858858+ let obj_data = RawData::Object(map.clone());
859859+ assert!(obj_data.as_object().is_some());
860860+ assert_eq!(obj_data.as_object().unwrap().len(), 1);
861861+ assert!(RawData::Null.as_object().is_none());
862862+863863+ // Test as_array
864864+ let arr_data = RawData::Array(vec![RawData::SignedInt(1), RawData::SignedInt(2)]);
865865+ assert!(arr_data.as_array().is_some());
866866+ assert_eq!(arr_data.as_array().unwrap().len(), 2);
867867+ assert!(RawData::Null.as_array().is_none());
868868+869869+ // Test as_str
870870+ let str_data = RawData::String("hello".into());
871871+ assert_eq!(str_data.as_str(), Some("hello"));
872872+ assert!(RawData::Null.as_str().is_none());
873873+874874+ // Test as_boolean
875875+ let bool_data = RawData::Boolean(true);
876876+ assert_eq!(bool_data.as_boolean(), Some(true));
877877+ assert!(RawData::Null.as_boolean().is_none());
878878+879879+ // Test is_null
880880+ assert!(RawData::Null.is_null());
881881+ assert!(!RawData::SignedInt(0).is_null());
882882+}
883883+884884+#[test]
885885+fn test_data_to_dag_cbor() {
886886+ // Test simple types
887887+ let null_data = Data::Null;
888888+ assert!(null_data.to_dag_cbor().is_ok());
889889+890890+ let int_data = Data::Integer(42);
891891+ assert!(int_data.to_dag_cbor().is_ok());
892892+893893+ let str_data = Data::String(AtprotoStr::String("hello".into()));
894894+ assert!(str_data.to_dag_cbor().is_ok());
895895+896896+ // Test complex types
897897+ let mut map = BTreeMap::new();
898898+ map.insert(SmolStr::new_static("num"), Data::Integer(42));
899899+ map.insert(SmolStr::new_static("text"), Data::String(AtprotoStr::String("test".into())));
900900+ let obj_data = Data::Object(Object(map));
901901+ let cbor_result = obj_data.to_dag_cbor();
902902+ assert!(cbor_result.is_ok());
903903+ assert!(!cbor_result.unwrap().is_empty());
904904+905905+ // Test array
906906+ let arr_data = Data::Array(Array(vec![Data::Integer(1), Data::Integer(2), Data::Integer(3)]));
907907+ let arr_cbor = arr_data.to_dag_cbor();
908908+ assert!(arr_cbor.is_ok());
909909+ assert!(!arr_cbor.unwrap().is_empty());
910910+}
911911+912912+#[test]
913913+fn test_rawdata_to_dag_cbor() {
914914+ // Test simple types
915915+ let null_data = RawData::Null;
916916+ assert!(null_data.to_dag_cbor().is_ok());
917917+918918+ let int_data = RawData::SignedInt(42);
919919+ assert!(int_data.to_dag_cbor().is_ok());
920920+921921+ let str_data = RawData::String("hello".into());
922922+ assert!(str_data.to_dag_cbor().is_ok());
923923+924924+ // Test complex types
925925+ let mut map = BTreeMap::new();
926926+ map.insert(SmolStr::new_static("num"), RawData::SignedInt(42));
927927+ map.insert(SmolStr::new_static("text"), RawData::String("test".into()));
928928+ let obj_data = RawData::Object(map);
929929+ let cbor_result = obj_data.to_dag_cbor();
930930+ assert!(cbor_result.is_ok());
931931+ assert!(!cbor_result.unwrap().is_empty());
932932+}
+1-1
crates/jacquard-derive/src/lib.rs
···167167/// **What it generates:**
168168/// - `impl LexiconSchema` with `nsid()`, `schema_id()`, and `lexicon_doc()` methods
169169/// - `validate()` method that checks constraints at runtime
170170-/// - `inventory::submit!` registration for schema discovery (Phase 3)
170170+/// - `inventory::submit!` registration for schema discovery
171171///
172172/// **Attributes:** `#[lexicon(...)]` and `#[nsid = "..."]` on types and fields.
173173/// See crate docs for full attribute reference and examples.
···5858pub mod from_ast;
5959pub mod type_mapping;
60606161-use crate::lexicon::{LexUserType, Lexicon, LexiconDoc};
6161+use crate::lexicon::LexiconDoc;
62626363/// Trait for types that can generate lexicon schemas
6464pub trait LexiconSchema {