1package sessionwire
2
3import (
4 "github.com/bnema/vev/internal/domain"
5 "github.com/bnema/vev/internal/protocol"
6 "github.com/bnema/vev/internal/protocol/wire"
7)
8
9func routeRefToWire(ref protocol.RouteRef) *wire.RouteRef {
10 return &wire.RouteRef{Key: ref.Key, Generation: ref.Generation}
11}
12
13func routeRefFromWire(message *wire.RouteRef) protocol.RouteRef {
14 if message == nil {
15 return protocol.RouteRef{}
16 }
17 return protocol.RouteRef{Key: message.GetKey(), Generation: message.GetGeneration()}
18}
19
20func attentionTargetToWire(target protocol.RouteAttentionTarget) (*wire.RouteAttentionTarget, error) {
21 if err := protocol.ValidateRouteLabel(target.SourceKey, true); err != nil {
22 return nil, err
23 }
24 if err := target.Ref.Validate(); err != nil {
25 return nil, err
26 }
27 if err := target.Target.Validate(); err != nil {
28 return nil, err
29 }
30 return &wire.RouteAttentionTarget{Ref: routeRefToWire(target.Ref), Target: exactTargetToWire(&target.Target), SourceKey: target.SourceKey}, nil
31}
32
33func attentionTargetFromWire(message *wire.RouteAttentionTarget) (protocol.RouteAttentionTarget, error) {
34 var target protocol.RouteAttentionTarget
35 if message == nil {
36 return target, protocol.ErrInvalidRouteWire
37 }
38 target.Ref = routeRefFromWire(message.GetRef())
39 exact, err := exactTargetFromWire(message.GetTarget())
40 if err != nil || exact == nil {
41 return protocol.RouteAttentionTarget{}, protocol.ErrInvalidRouteWire
42 }
43 target.Target = *exact
44 target.SourceKey = message.GetSourceKey()
45 return target, nil
46}
47
48func attentionSubscriptionToWire(message protocol.RouteAttentionSubscription) (*wire.RouteAttentionSubscription, error) {
49 if err := message.Validate(); err != nil {
50 return nil, err
51 }
52 out := &wire.RouteAttentionSubscription{}
53 for _, target := range message.Targets {
54 converted, err := attentionTargetToWire(target)
55 if err != nil {
56 return nil, err
57 }
58 out.Targets = append(out.Targets, converted)
59 }
60 return out, nil
61}
62
63func recentRouteEntryToWire(entry protocol.RecentRouteEntry) (*wire.RecentRouteEntry, error) {
64 return &wire.RecentRouteEntry{
65 Key: entry.Key,
66 Generation: entry.Generation,
67 Target: exactTargetToWire(&entry.Target),
68 Name: entry.Name,
69 HostLabel: entry.HostLabel,
70 Kind: uint32(entry.Kind),
71 Ephemeral: entry.Ephemeral,
72 Attention: entry.Attention,
73 Reachability: uint32(entry.Reachability),
74 AttentionSeq: entry.AttentionSeq,
75 Visited: entry.Visited,
76 }, nil
77}
78
79func routeHostToWire(host protocol.RouteHost) *wire.RouteHost {
80 return &wire.RouteHost{Key: host.Key, Generation: host.Generation, Label: host.Label, Kind: uint32(host.Kind)}
81}
82
83func routeHostFromWire(message *wire.RouteHost) (protocol.RouteHost, error) {
84 if message == nil {
85 return protocol.RouteHost{}, protocol.ErrInvalidRouteWire
86 }
87 kind, err := enum8[protocol.RouteKind](message.GetKind())
88 if err != nil {
89 return protocol.RouteHost{}, err
90 }
91 return protocol.RouteHost{Key: message.GetKey(), Generation: message.GetGeneration(), Label: message.GetLabel(), Kind: kind}, nil
92}
93
94func recentRouteEntryFromWire(message *wire.RecentRouteEntry) (protocol.RecentRouteEntry, error) {
95 var entry protocol.RecentRouteEntry
96 if message == nil {
97 return entry, protocol.ErrInvalidRouteWire
98 }
99 entry.Key = message.GetKey()
100 entry.Generation = message.GetGeneration()
101 target, err := exactTargetFromWire(message.GetTarget())
102 if err != nil || target == nil {
103 return protocol.RecentRouteEntry{}, protocol.ErrInvalidRouteWire
104 }
105 entry.Target = *target
106 entry.Name = message.GetName()
107 entry.HostLabel = message.GetHostLabel()
108 entry.Kind, err = enum8[protocol.RouteKind](message.GetKind())
109 if err != nil {
110 return protocol.RecentRouteEntry{}, err
111 }
112 entry.Ephemeral = message.GetEphemeral()
113 entry.Attention = message.GetAttention()
114 entry.Reachability, err = enum8[protocol.RouteReachability](message.GetReachability())
115 if err != nil {
116 return protocol.RecentRouteEntry{}, err
117 }
118 entry.AttentionSeq = message.GetAttentionSeq()
119 entry.Visited = message.GetVisited()
120 return entry, nil
121}
122
123func navigationFailureToWire(failure protocol.RouteNavigationFailure) (*wire.RouteNavigationFailure, error) {
124 if err := failure.Validate(); err != nil {
125 return nil, err
126 }
127 return &wire.RouteNavigationFailure{Key: failure.Key, Generation: failure.Generation, Code: uint32(failure.Code)}, nil
128}
129
130func navigationFailureFromWire(message *wire.RouteNavigationFailure) (protocol.RouteNavigationFailure, error) {
131 var failure protocol.RouteNavigationFailure
132 if message == nil {
133 return failure, protocol.ErrInvalidRouteWire
134 }
135 failure.Key = message.GetKey()
136 failure.Generation = message.GetGeneration()
137 code, err := enum8[protocol.RouteFailureCode](message.GetCode())
138 if err != nil {
139 return protocol.RouteNavigationFailure{}, err
140 }
141 failure.Code = code
142 if err := failure.Validate(); err != nil {
143 return protocol.RouteNavigationFailure{}, err
144 }
145 return failure, nil
146}
147
148func inventoryGroupsToWire(groups []protocol.NavigationInventorySourceGroup) ([]*wire.InventorySourceGroup, error) {
149 if len(groups) == 0 {
150 return nil, nil
151 }
152 out := make([]*wire.InventorySourceGroup, 0, len(groups))
153 for _, group := range groups {
154 converted := &wire.InventorySourceGroup{SourceKey: group.SourceKey, Status: uint32(group.Status)}
155 for _, entry := range group.Entries {
156 converted.Entries = append(converted.Entries, &wire.InventoryEntry{
157 SourceKey: entry.SourceKey,
158 EntryKey: entry.EntryKey,
159 Name: entry.Name,
160 DisplayOrigin: entry.DisplayOrigin,
161 State: entry.State,
162 Reason: entry.Reason,
163 })
164 }
165 out = append(out, converted)
166 }
167 return out, nil
168}
169
170func inventoryGroupsFromWire(groups []*wire.InventorySourceGroup) ([]protocol.NavigationInventorySourceGroup, error) {
171 if len(groups) == 0 {
172 return nil, nil
173 }
174 out := make([]protocol.NavigationInventorySourceGroup, 0, len(groups))
175 for _, group := range groups {
176 status, err := enum8[protocol.NavigationInventorySourceStatus](group.GetStatus())
177 if err != nil {
178 return nil, err
179 }
180 converted := protocol.NavigationInventorySourceGroup{SourceKey: group.GetSourceKey(), Status: status}
181 for _, entry := range group.GetEntries() {
182 converted.Entries = append(converted.Entries, protocol.NavigationInventoryEntry{
183 SourceKey: entry.GetSourceKey(),
184 EntryKey: entry.GetEntryKey(),
185 Name: entry.GetName(),
186 DisplayOrigin: entry.GetDisplayOrigin(),
187 State: entry.GetState(),
188 Reason: entry.GetReason(),
189 })
190 }
191 out = append(out, converted)
192 }
193 return out, nil
194}
195
196func inventoryRequestToWire(message protocol.NavigationInventoryRequest) (*wire.NavigationInventoryRequest, error) {
197 if err := protocol.ValidateNavigationInventoryRequest(message); err != nil {
198 return nil, err
199 }
200 var registration *wire.RemoteRegistration
201 if !message.Registration.IsZero() {
202 registration = registrationToWire(message.Registration)
203 }
204 return &wire.NavigationInventoryRequest{
205 Version: uint32(message.Version),
206 RequestId: message.RequestID,
207 Operation: uint32(message.Operation),
208 SourceKey: message.SourceKey,
209 EntryKey: message.EntryKey,
210 Registration: registration,
211 }, nil
212}
213
214func inventoryRequestFromWire(message *wire.NavigationInventoryRequest) (protocol.NavigationInventoryRequest, error) {
215 var request protocol.NavigationInventoryRequest
216 if message == nil {
217 return request, protocol.ErrInvalidNavigation
218 }
219 version, err := mustUint16(message.GetVersion())
220 if err != nil {
221 return protocol.NavigationInventoryRequest{}, protocol.ErrInvalidNavigation
222 }
223 request.Version = version
224 request.RequestID = message.GetRequestId()
225 request.Operation, err = enum8[protocol.NavigationInventoryOperation](message.GetOperation())
226 if err != nil {
227 return protocol.NavigationInventoryRequest{}, protocol.ErrInvalidNavigation
228 }
229 request.SourceKey = message.GetSourceKey()
230 request.EntryKey = message.GetEntryKey()
231 registration, err := registrationFromWire(message.GetRegistration())
232 if err != nil {
233 return protocol.NavigationInventoryRequest{}, protocol.ErrInvalidNavigation
234 }
235 request.Registration = registration
236 if request.Registration == (domain.RemoteRegistration{}) && message.GetRegistration() != nil {
237 return protocol.NavigationInventoryRequest{}, protocol.ErrInvalidNavigation
238 }
239 if err := protocol.ValidateNavigationInventoryRequest(request); err != nil {
240 return protocol.NavigationInventoryRequest{}, err
241 }
242 return request, nil
243}
244
245func pickerLineToWire(line protocol.PickerLine) *wire.PickerLine {
246 return &wire.PickerLine{
247 Key: line.Key,
248 Kind: uint32(line.Kind),
249 Label: line.Label,
250 Detail: line.Detail,
251 Status: uint32(line.Status),
252 StatusDetail: line.StatusDetail,
253 Attention: line.Attention,
254 Stopped: line.Stopped,
255 Dim: line.Dim,
256 Focusable: line.Focusable,
257 Actions: uint32(line.Actions),
258 Ephemeral: line.Ephemeral,
259 }
260}
261
262func pickerLineFromWire(message *wire.PickerLine) (protocol.PickerLine, error) {
263 var line protocol.PickerLine
264 if message == nil {
265 return line, protocol.ErrInvalidNavigation
266 }
267 line.Key = message.GetKey()
268 kind, err := enum8[protocol.PickerLineKind](message.GetKind())
269 if err != nil {
270 return protocol.PickerLine{}, protocol.ErrInvalidNavigation
271 }
272 line.Kind = kind
273 line.Label = message.GetLabel()
274 line.Detail = message.GetDetail()
275 status, err := enum8[protocol.PickerLineStatus](message.GetStatus())
276 if err != nil {
277 return protocol.PickerLine{}, protocol.ErrInvalidNavigation
278 }
279 line.Status = status
280 line.StatusDetail = message.GetStatusDetail()
281 line.Attention = message.GetAttention()
282 line.Stopped = message.GetStopped()
283 line.Dim = message.GetDim()
284 line.Focusable = message.GetFocusable()
285 actions, err := enum8[protocol.PickerLineActions](message.GetActions())
286 if err != nil {
287 return protocol.PickerLine{}, protocol.ErrInvalidNavigation
288 }
289 line.Actions = actions
290 line.Ephemeral = message.GetEphemeral()
291 return line, nil
292}
293
294func pickerCursorToWire(cursor protocol.PickerCursor) *wire.PickerCursor {
295 return &wire.PickerCursor{Key: cursor.Key, Index: int64(cursor.Index)}
296}
297
298func pickerCursorFromWire(message *wire.PickerCursor) (protocol.PickerCursor, error) {
299 var cursor protocol.PickerCursor
300 if message == nil {
301 return cursor, nil
302 }
303 index := message.GetIndex()
304 if index < 0 || index > int64(int(^uint(0)>>1)) {
305 return protocol.PickerCursor{}, errProtoConvertRange
306 }
307 return protocol.PickerCursor{Key: message.GetKey(), Index: int(index)}, nil
308}
309
310func pickerProjectionToWire(projection protocol.PickerProjection) (*wire.PickerProjection, error) {
311 out := &wire.PickerProjection{Cursor: pickerCursorToWire(projection.Cursor)}
312 for _, line := range projection.Lines {
313 out.Lines = append(out.Lines, pickerLineToWire(line))
314 }
315 return out, nil
316}
317
318func pickerProjectionFromWire(message *wire.PickerProjection) (protocol.PickerProjection, error) {
319 var projection protocol.PickerProjection
320 if message == nil {
321 return projection, nil
322 }
323 cursor, err := pickerCursorFromWire(message.GetCursor())
324 if err != nil {
325 return protocol.PickerProjection{}, err
326 }
327 projection.Cursor = cursor
328 for _, line := range message.GetLines() {
329 converted, err := pickerLineFromWire(line)
330 if err != nil {
331 return protocol.PickerProjection{}, err
332 }
333 projection.Lines = append(projection.Lines, converted)
334 }
335 return projection, nil
336}
337
338func pickerSnapshotToWire(snapshot protocol.PickerSnapshot) (*wire.PickerSnapshot, error) {
339 snapshot = protocol.NormalizePickerSnapshot(snapshot)
340 if err := protocol.ValidatePickerSnapshot(snapshot); err != nil {
341 return nil, err
342 }
343 recent, err := pickerProjectionToWire(snapshot.Recent)
344 if err != nil {
345 return nil, err
346 }
347 grouped, err := pickerProjectionToWire(snapshot.Grouped)
348 if err != nil {
349 return nil, err
350 }
351 return &wire.PickerSnapshot{
352 InteractionId: snapshot.InteractionID,
353 SourceId: snapshot.SourceID,
354 SourceRevision: snapshot.SourceRevision,
355 Status: uint32(snapshot.Status),
356 StatusDetail: snapshot.StatusDetail,
357 Recent: recent,
358 Grouped: grouped,
359 }, nil
360}
361
362func pickerSnapshotFromWire(message *wire.PickerSnapshot) (protocol.PickerSnapshot, error) {
363 var snapshot protocol.PickerSnapshot
364 if message == nil {
365 return snapshot, protocol.ErrInvalidNavigation
366 }
367 snapshot.InteractionID = message.GetInteractionId()
368 snapshot.SourceID = message.GetSourceId()
369 snapshot.SourceRevision = message.GetSourceRevision()
370 status, err := enum8[protocol.PickerSourceStatus](message.GetStatus())
371 if err != nil {
372 return protocol.PickerSnapshot{}, err
373 }
374 snapshot.Status = status
375 snapshot.StatusDetail = message.GetStatusDetail()
376 recent, err := pickerProjectionFromWire(message.GetRecent())
377 if err != nil {
378 return protocol.PickerSnapshot{}, err
379 }
380 snapshot.Recent = recent
381 grouped, err := pickerProjectionFromWire(message.GetGrouped())
382 if err != nil {
383 return protocol.PickerSnapshot{}, err
384 }
385 snapshot.Grouped = grouped
386 snapshot = protocol.NormalizePickerSnapshot(snapshot)
387 if err := protocol.ValidatePickerSnapshot(snapshot); err != nil {
388 return protocol.PickerSnapshot{}, err
389 }
390 // Lines/Cursor are construction aliases: repopulate them from the
391 // normalized projections so decoded snapshots behave like the
392 // snapshots the daemon built before encoding.
393 snapshot.Lines = append([]protocol.PickerLine(nil), snapshot.Recent.Lines...)
394 snapshot.Cursor = snapshot.Recent.Cursor
395 return snapshot, nil
396}