main ece7682

proto_convert_shared.go RawHistoryFolder

1// Protobuf semantic converters.
2//
3// This file owns every semantic protocol value <-> generated wire envelope
4// conversion used by client.go/server.go dispatch. The actual field-by-field
5// conversion logic lives in internal/adapters/protoconv, the single
6// canonical implementation shared with brokerwire; the wrappers below adapt
7// protoconv's shared ErrOutOfRange (and, for the RemotePreview family,
8// protocol's own validation sentinels) to this package's local
9// errProtoConvertRange, and add the pointer/nil-tolerance policy specific to
10// sessionwire's call sites. Use cases always see uncompressed terminal data.
11package sessionwire
12
13import (
14	"errors"
15
16	renderer "github.com/bnema/vev-vt"
17	"github.com/bnema/vev/internal/adapters/protoconv"
18	"github.com/bnema/vev/internal/domain"
19	"github.com/bnema/vev/internal/protocol"
20	"github.com/bnema/vev/internal/protocol/wire"
21)
22
23var errProtoConvertRange = errors.New("sessionwire: wire value out of semantic range")
24
25func mustUint16(v uint32) (uint16, error) {
26	out, err := protoconv.Uint16[uint16](v)
27	if err != nil {
28		return 0, errProtoConvertRange
29	}
30	return out, nil
31}
32
33func mustUint8(v uint32) (uint8, error) {
34	out, err := protoconv.Uint8[uint8](v)
35	if err != nil {
36		return 0, errProtoConvertRange
37	}
38	return out, nil
39}
40
41// enum8 narrows one wire uint32 into an 8-bit semantic enum. Values whose
42// high bits would otherwise truncate into a valid enum range are refused
43// before any cast, so hostile wire input cannot alias a legitimate value.
44func enum8[T ~uint8](value uint32) (T, error) {
45	out, err := protoconv.Uint8[T](value)
46	if err != nil {
47		return 0, errProtoConvertRange
48	}
49	return out, nil
50}
51
52func mustTabIDString(value string) domain.TabStableID { return domain.TabStableID(value) }
53
54func lifecycleToWire(id domain.SessionLifecycleID) *wire.LifecycleID {
55	return protoconv.LifecycleToWire(id)
56}
57
58func lifecycleFromWire(message *wire.LifecycleID) (domain.SessionLifecycleID, error) {
59	id, err := protoconv.LifecycleFromWire(message)
60	if err != nil {
61		return domain.SessionLifecycleID{}, errProtoConvertRange
62	}
63	return id, nil
64}
65
66func exactTargetToWire(target *protocol.ExactSessionTarget) *wire.ExactTarget {
67	if target == nil {
68		return nil
69	}
70	return &wire.ExactTarget{LifecycleId: lifecycleToWire(target.LifecycleID), SessionName: target.SessionName}
71}
72
73func exactTargetFromWire(message *wire.ExactTarget) (*protocol.ExactSessionTarget, error) {
74	if message == nil {
75		return nil, nil
76	}
77	lifecycle, err := lifecycleFromWire(message.GetLifecycleId())
78	if err != nil {
79		return nil, err
80	}
81	return &protocol.ExactSessionTarget{LifecycleID: lifecycle, SessionName: message.GetSessionName()}, nil
82}
83
84func rgbToWire(color renderer.RGB) *wire.RGB {
85	return protoconv.RGBToWire(color)
86}
87
88func rgbFromWire(message *wire.RGB) (renderer.RGB, error) {
89	color, err := protoconv.RGBFromWire(message)
90	if err != nil {
91		return renderer.RGB{}, errProtoConvertRange
92	}
93	return color, nil
94}
95
96func registrationToWire(registration domain.RemoteRegistration) *wire.RemoteRegistration {
97	incarnation := append([]byte(nil), registration.Incarnation[:]...)
98	return &wire.RemoteRegistration{Endpoint: registration.Endpoint, Incarnation: incarnation, Generation: uint64(registration.Generation)}
99}
100
101func registrationFromWire(message *wire.RemoteRegistration) (domain.RemoteRegistration, error) {
102	var registration domain.RemoteRegistration
103	if message == nil {
104		return registration, nil
105	}
106	registration.Endpoint = message.GetEndpoint()
107	if len(message.GetIncarnation()) != len(registration.Incarnation) {
108		return domain.RemoteRegistration{}, errProtoConvertRange
109	}
110	copy(registration.Incarnation[:], message.GetIncarnation())
111	registration.Generation = domain.RemoteGeneration(message.GetGeneration())
112	return registration, nil
113}

Keyboard shortcuts

Single-key shortcuts are on. ctrl k and esc work whatever this says.

ctrl k :
go to a section, branch, tag, file or repository
?
this list
j k
move the row cursor down / up
enter
open the row under the cursor; on Files, a directory opens or closes in place
↑ ↓ ← → home end
in the file tree (focus on a row): previous / next row, close / open a directory or go to its parent / first entry, first / last row. They never open a file
l h
on Files: open a directory or a file / close a directory or go up to its parent, then to the parent page. Elsewhere: into the side panel (on a merge request, its files) / back to the content; there j k move between its controls
g g G
first / last row
/
filter the list; on Files, find a file anywhere in the repository (esc clears, enter opens the best match)
b
switch branch or tag
g s g f g c g b g m g i g r g a
tabs: summary, files, commits, branches & tags, merge requests, issues, releases, actions (when available)
g h
home
w
wide mode: use the whole width of the screen, or not (remembered)
y
copy a permalink pinned to the commit
d u x
diff: split / unified / collapse or expand all
e E
diff: the whole file in view / every file, with the lines the hunks hide
n
merge request: next note in the diff
esc
close a dialog, leave a field

Branches 12

Tags 11

↑↓ moveenter openesc close