plc.directory mirror
1package plc
2
3import (
4 "encoding/json"
5 "fmt"
6)
7
8type OperationType string
9
10const (
11 OperationTypePLC OperationType = "plc_operation"
12 OperationTypeTombstone OperationType = "plc_tombstone"
13 OperationTypeCreate OperationType = "create"
14)
15
16type ServiceEndpoint struct {
17 Type string `json:"type"`
18 Endpoint string `json:"endpoint"`
19}
20
21type Operation struct {
22 Type OperationType `json:"type"`
23 RotationKeys []string `json:"rotationKeys"`
24 VerificationMethods map[string]string `json:"verificationMethods"`
25 AlsoKnownAs []string `json:"alsoKnownAs"`
26 Services map[string]ServiceEndpoint `json:"services"`
27 Prev *string `json:"prev"`
28 Sig string `json:"sig"`
29}
30
31type TombstoneOperation struct {
32 Type OperationType `json:"type"`
33 Prev string `json:"prev"`
34 Sig string `json:"sig"`
35}
36
37type DeprecatedOperation struct {
38 Type OperationType `json:"type"`
39 SigningKey string `json:"signingKey"`
40 RecoveryKey string `json:"recoveryKey"`
41 Handle string `json:"handle"`
42 Service string `json:"service"`
43 Prev *string `json:"prev"`
44 Sig string `json:"sig"`
45}
46
47type PLCOperation struct {
48 *Operation
49 *TombstoneOperation
50 *DeprecatedOperation
51}
52
53func (op *PLCOperation) UnmarshalJSON(data []byte) error {
54 var typeOnly struct {
55 Type OperationType `json:"type"`
56 }
57
58 if err := json.Unmarshal(data, &typeOnly); err != nil {
59 return fmt.Errorf("failed to unmarshal operation type: %w", err)
60 }
61
62 switch typeOnly.Type {
63 case OperationTypePLC:
64 var regular Operation
65 if err := json.Unmarshal(data, ®ular); err != nil {
66 return fmt.Errorf("failed to unmarshal plc_operation: %w", err)
67 }
68 op.Operation = ®ular
69
70 case OperationTypeTombstone:
71 var tombstone TombstoneOperation
72 if err := json.Unmarshal(data, &tombstone); err != nil {
73 return fmt.Errorf("failed to unmarshal plc_tombstone: %w", err)
74 }
75 op.TombstoneOperation = &tombstone
76
77 case OperationTypeCreate:
78 var deprecated DeprecatedOperation
79 if err := json.Unmarshal(data, &deprecated); err != nil {
80 return fmt.Errorf("failed to unmarshal deprecated create operation: %w", err)
81 }
82 op.DeprecatedOperation = &deprecated
83
84 default:
85 return fmt.Errorf("unknown operation type: %s", typeOnly.Type)
86 }
87
88 return nil
89}
90
91func (op PLCOperation) MarshalJSON() ([]byte, error) {
92 if op.Operation != nil {
93 return json.Marshal(op.Operation)
94 }
95 if op.TombstoneOperation != nil {
96 return json.Marshal(op.TombstoneOperation)
97 }
98 if op.DeprecatedOperation != nil {
99 return json.Marshal(op.DeprecatedOperation)
100 }
101 return nil, fmt.Errorf("no valid operation data to marshal")
102}
103
104func (op PLCOperation) GetType() OperationType {
105 if op.Operation != nil {
106 return op.Operation.Type
107 }
108 if op.TombstoneOperation != nil {
109 return op.TombstoneOperation.Type
110 }
111 if op.DeprecatedOperation != nil {
112 return op.DeprecatedOperation.Type
113 }
114 return ""
115}