A better Rust ATProto crate
1use super::CodeGenerator; 2use crate::lexicon::{ 3 LexArrayItem, LexObjectProperty, LexString, LexStringFormat, LexUserType, 4}; 5 6impl<'c> CodeGenerator<'c> { 7 /// Check if a property type needs a lifetime parameter 8 pub(super) fn property_needs_lifetime(&self, prop: &LexObjectProperty<'static>) -> bool { 9 match prop { 10 LexObjectProperty::Boolean(_) | LexObjectProperty::Integer(_) => false, 11 LexObjectProperty::String(s) => self.string_needs_lifetime(s), 12 LexObjectProperty::Bytes(_) => false, // Bytes is owned 13 LexObjectProperty::CidLink(_) 14 | LexObjectProperty::Blob(_) 15 | LexObjectProperty::Unknown(_) => true, 16 LexObjectProperty::Array(array) => self.array_item_needs_lifetime(&array.items), 17 LexObjectProperty::Object(_) => true, // Nested objects have lifetimes 18 LexObjectProperty::Ref(ref_type) => { 19 // Check if the ref target actually needs a lifetime 20 self.ref_needs_lifetime(&ref_type.r#ref) 21 } 22 LexObjectProperty::Union(_) => true, // Unions generally have lifetimes 23 } 24 } 25 26 /// Check if an array item type needs a lifetime parameter 27 pub(super) fn array_item_needs_lifetime(&self, item: &LexArrayItem) -> bool { 28 match item { 29 LexArrayItem::Boolean(_) | LexArrayItem::Integer(_) => false, 30 LexArrayItem::String(s) => self.string_needs_lifetime(s), 31 LexArrayItem::Bytes(_) => false, 32 LexArrayItem::CidLink(_) | LexArrayItem::Blob(_) | LexArrayItem::Unknown(_) => true, 33 LexArrayItem::Object(_) => true, // Nested objects have lifetimes 34 LexArrayItem::Ref(ref_type) => self.ref_needs_lifetime(&ref_type.r#ref), 35 LexArrayItem::Union(_) => true, 36 } 37 } 38 39 /// Check if a string type needs a lifetime parameter 40 pub(super) fn string_needs_lifetime(&self, s: &LexString) -> bool { 41 match s.format { 42 Some(LexStringFormat::Datetime) 43 | Some(LexStringFormat::Language) 44 | Some(LexStringFormat::Tid) => false, 45 _ => true, // Most string types borrow 46 } 47 } 48 49 /// Check if a ref needs a lifetime parameter 50 pub(super) fn ref_needs_lifetime(&self, ref_str: &str) -> bool { 51 // Try to resolve the ref 52 if let Some((_doc, def)) = self.corpus.resolve_ref(ref_str) { 53 self.def_needs_lifetime(def) 54 } else { 55 // If we can't resolve it, assume it needs a lifetime (safe default) 56 true 57 } 58 } 59 60 /// Check if a lexicon def needs a lifetime parameter 61 pub(super) fn def_needs_lifetime(&self, def: &LexUserType<'static>) -> bool { 62 match def { 63 // Records and Objects always have lifetimes now since they get #[lexicon] attribute 64 LexUserType::Record(_) => true, 65 LexUserType::Object(_) => true, 66 LexUserType::Token(_) => false, 67 LexUserType::String(s) => { 68 // Check if it's a known values enum or a regular string 69 if s.known_values.is_some() { 70 // Known values enums have Other(CowStr<'a>) variant 71 true 72 } else { 73 self.string_needs_lifetime(s) 74 } 75 } 76 LexUserType::Integer(_) => false, 77 LexUserType::Boolean(_) => false, 78 LexUserType::Bytes(_) => false, 79 LexUserType::CidLink(_) | LexUserType::Blob(_) | LexUserType::Unknown(_) => true, 80 LexUserType::Array(array) => self.array_item_needs_lifetime(&array.items), 81 LexUserType::XrpcQuery(_) 82 | LexUserType::XrpcProcedure(_) 83 | LexUserType::XrpcSubscription(_) => { 84 // XRPC types generate multiple structs, not a single type we can reference 85 // Shouldn't be referenced directly 86 true 87 } 88 } 89 } 90 91 /// Check if xrpc params need a lifetime parameter 92 pub(super) fn params_need_lifetime(&self, params: &crate::lexicon::LexXrpcParameters<'static>) -> bool { 93 params.properties.values().any(|prop| { 94 use crate::lexicon::LexXrpcParametersProperty; 95 match prop { 96 LexXrpcParametersProperty::Boolean(_) | LexXrpcParametersProperty::Integer(_) => { 97 false 98 } 99 LexXrpcParametersProperty::String(s) => self.string_needs_lifetime(s), 100 LexXrpcParametersProperty::Unknown(_) => true, 101 LexXrpcParametersProperty::Array(arr) => { 102 use crate::lexicon::LexPrimitiveArrayItem; 103 match &arr.items { 104 LexPrimitiveArrayItem::Boolean(_) | LexPrimitiveArrayItem::Integer(_) => { 105 false 106 } 107 LexPrimitiveArrayItem::String(s) => self.string_needs_lifetime(s), 108 LexPrimitiveArrayItem::Unknown(_) => true, 109 } 110 } 111 } 112 }) 113 } 114}