@@ -374,7 +374,7 @@ pub struct TypedResourceSetupChangeItem<'a, F: TargetFactoryBase + ?Sized> {
374374}
375375
376376#[ async_trait]
377- pub trait TargetFactoryBase : TargetFactory + Send + Sync + ' static {
377+ pub trait TargetFactoryBase : Send + Sync + ' static {
378378 type Spec : DeserializeOwned + Send + Sync ;
379379 type DeclarationSpec : DeserializeOwned + Send + Sync ;
380380
@@ -635,3 +635,79 @@ fn from_json_combined_state<T: Debug + Clone + Serialize + DeserializeOwned>(
635635 legacy_state_key : existing_states. legacy_state_key ,
636636 } )
637637}
638+
639+ pub struct TypedTargetAttachmentState < F : TargetSpecificAttachmentFactoryBase + ?Sized > {
640+ pub setup_key : F :: SetupKey ,
641+ pub setup_state : F :: SetupState ,
642+ }
643+
644+ /// A factory for target-specific attachments.
645+ pub trait TargetSpecificAttachmentFactoryBase : Send + Sync + ' static {
646+ type TargetSpec : DeserializeOwned + Send + Sync ;
647+ type Spec : DeserializeOwned + Send + Sync ;
648+ type SetupKey : Debug + Clone + Serialize + DeserializeOwned + Eq + Hash + Send + Sync ;
649+ type SetupState : Debug + Clone + Serialize + DeserializeOwned + Send + Sync ;
650+ type SetupChange : interface:: AttachmentSetupChange + Send + Sync ;
651+
652+ fn get_state (
653+ & self ,
654+ target_name : & str ,
655+ target_spec : & Self :: TargetSpec ,
656+ attachment_spec : Self :: Spec ,
657+ ) -> Result < TypedTargetAttachmentState < Self > > ;
658+
659+ fn diff_setup_states (
660+ & self ,
661+ key : & serde_json:: Value ,
662+ new_state : Option < serde_json:: Value > ,
663+ existing_states : setup:: CombinedState < serde_json:: Value > ,
664+ ) -> Result < Option < Self :: SetupChange > > ;
665+
666+ /// Deserialize the setup key from a JSON value.
667+ /// You can override this method to provide a custom deserialization logic, e.g. to perform backward compatible deserialization.
668+ fn deserialize_setup_key ( key : serde_json:: Value ) -> Result < Self :: SetupKey > {
669+ Ok ( utils:: deser:: from_json_value ( key) ?)
670+ }
671+ }
672+
673+ #[ async_trait]
674+ impl < T : TargetSpecificAttachmentFactoryBase > TargetAttachmentFactory for T {
675+ fn normalize_setup_key ( & self , key : & serde_json:: Value ) -> Result < serde_json:: Value > {
676+ let key: T :: SetupKey = Self :: deserialize_setup_key ( key. clone ( ) ) ?;
677+ Ok ( serde_json:: to_value ( key) ?)
678+ }
679+
680+ fn get_state (
681+ & self ,
682+ target_name : & str ,
683+ target_spec : & serde_json:: Map < String , serde_json:: Value > ,
684+ attachment_spec : serde_json:: Value ,
685+ ) -> Result < interface:: TargetAttachmentState > {
686+ let state = TargetSpecificAttachmentFactoryBase :: get_state (
687+ self ,
688+ target_name,
689+ & utils:: deser:: from_json_value ( serde_json:: Value :: Object ( target_spec. clone ( ) ) ) ?,
690+ utils:: deser:: from_json_value ( attachment_spec) ?,
691+ ) ?;
692+ Ok ( interface:: TargetAttachmentState {
693+ setup_key : serde_json:: to_value ( state. setup_key ) ?,
694+ setup_state : serde_json:: to_value ( state. setup_state ) ?,
695+ } )
696+ }
697+
698+ fn diff_setup_states (
699+ & self ,
700+ key : & serde_json:: Value ,
701+ new_state : Option < serde_json:: Value > ,
702+ existing_states : setup:: CombinedState < serde_json:: Value > ,
703+ ) -> Result < Option < Box < dyn AttachmentSetupChange + Send + Sync > > > {
704+ let setup_change = self . diff_setup_states (
705+ & utils:: deser:: from_json_value ( key. clone ( ) ) ?,
706+ new_state
707+ . map ( |v| utils:: deser:: from_json_value ( v) )
708+ . transpose ( ) ?,
709+ from_json_combined_state ( existing_states) ?,
710+ ) ?;
711+ Ok ( setup_change. map ( |s| Box :: new ( s) as Box < dyn AttachmentSetupChange + Send + Sync > ) )
712+ }
713+ }
0 commit comments