package plc import ( "encoding/json" "fmt" ) type OperationType string const ( OperationTypePLC OperationType = "plc_operation" OperationTypeTombstone OperationType = "plc_tombstone" OperationTypeCreate OperationType = "create" ) type ServiceEndpoint struct { Type string `json:"type"` Endpoint string `json:"endpoint"` } type Operation struct { Type OperationType `json:"type"` RotationKeys []string `json:"rotationKeys"` VerificationMethods map[string]string `json:"verificationMethods"` AlsoKnownAs []string `json:"alsoKnownAs"` Services map[string]ServiceEndpoint `json:"services"` Prev *string `json:"prev"` Sig string `json:"sig"` } type TombstoneOperation struct { Type OperationType `json:"type"` Prev string `json:"prev"` Sig string `json:"sig"` } type DeprecatedOperation struct { Type OperationType `json:"type"` SigningKey string `json:"signingKey"` RecoveryKey string `json:"recoveryKey"` Handle string `json:"handle"` Service string `json:"service"` Prev *string `json:"prev"` Sig string `json:"sig"` } type PLCOperation struct { *Operation *TombstoneOperation *DeprecatedOperation } func (op *PLCOperation) UnmarshalJSON(data []byte) error { var typeOnly struct { Type OperationType `json:"type"` } if err := json.Unmarshal(data, &typeOnly); err != nil { return fmt.Errorf("failed to unmarshal operation type: %w", err) } switch typeOnly.Type { case OperationTypePLC: var regular Operation if err := json.Unmarshal(data, ®ular); err != nil { return fmt.Errorf("failed to unmarshal plc_operation: %w", err) } op.Operation = ®ular case OperationTypeTombstone: var tombstone TombstoneOperation if err := json.Unmarshal(data, &tombstone); err != nil { return fmt.Errorf("failed to unmarshal plc_tombstone: %w", err) } op.TombstoneOperation = &tombstone case OperationTypeCreate: var deprecated DeprecatedOperation if err := json.Unmarshal(data, &deprecated); err != nil { return fmt.Errorf("failed to unmarshal deprecated create operation: %w", err) } op.DeprecatedOperation = &deprecated default: return fmt.Errorf("unknown operation type: %s", typeOnly.Type) } return nil } func (op PLCOperation) MarshalJSON() ([]byte, error) { if op.Operation != nil { return json.Marshal(op.Operation) } if op.TombstoneOperation != nil { return json.Marshal(op.TombstoneOperation) } if op.DeprecatedOperation != nil { return json.Marshal(op.DeprecatedOperation) } return nil, fmt.Errorf("no valid operation data to marshal") } func (op PLCOperation) GetType() OperationType { if op.Operation != nil { return op.Operation.Type } if op.TombstoneOperation != nil { return op.TombstoneOperation.Type } if op.DeprecatedOperation != nil { return op.DeprecatedOperation.Type } return "" }