| 1 | package workspacestate |
| 2 | |
| 3 | import ( |
| 4 | "bytes" |
| 5 | "maps" |
| 6 | "slices" |
| 7 | ) |
| 8 | |
| 9 | // Keep the decoded cache private. Every reader owns all of its mutable data, |
| 10 | // including fields retained for a newer writer that this version cannot see. |
| 11 | func cloneSnapshot(s State) State { |
| 12 | s.TopicRemovals = maps.Clone(s.TopicRemovals) |
| 13 | for id, removal := range s.TopicRemovals { |
| 14 | removal.Snapshot = bytes.Clone(removal.Snapshot) |
| 15 | removal.Metadata = bytes.Clone(removal.Metadata) |
| 16 | removal.extra = cloneUnknownFields(removal.extra) |
| 17 | s.TopicRemovals[id] = removal |
| 18 | } |
| 19 | s.extra = cloneUnknownFields(s.extra) |
| 20 | s.WorkspaceIDs = slices.Clone(s.WorkspaceIDs) |
| 21 | s.ArchivedSessionIDs = slices.Clone(s.ArchivedSessionIDs) |
| 22 | s.Workspaces = maps.Clone(s.Workspaces) |
| 23 | for id, w := range s.Workspaces { |
| 24 | w.SessionIDs = slices.Clone(w.SessionIDs) |
| 25 | w.FormerRoots = slices.Clone(w.FormerRoots) |
| 26 | w.extra = cloneUnknownFields(w.extra) |
| 27 | if w.Organization != nil { |
| 28 | o := w.Organization.Clone() |
| 29 | w.Organization = &o |
| 30 | } |
| 31 | s.Workspaces[id] = w |
| 32 | } |
| 33 | s.PendingCreates = maps.Clone(s.PendingCreates) |
| 34 | for id, p := range s.PendingCreates { |
| 35 | p.extra = cloneUnknownFields(p.extra) |
| 36 | p.Presentation = clonePresentation(p.Presentation) |
| 37 | s.PendingCreates[id] = p |
| 38 | } |
| 39 | s.SessionStates = maps.Clone(s.SessionStates) |
| 40 | for id, status := range s.SessionStates { |
| 41 | status.extra = cloneUnknownFields(status.extra) |
| 42 | s.SessionStates[id] = status |
| 43 | } |
| 44 | s.SourceMappings = maps.Clone(s.SourceMappings) |
| 45 | for id, m := range s.SourceMappings { |
| 46 | s.SourceMappings[id] = cloneSourceMapping(m) |
| 47 | } |
| 48 | s.PendingOperations = maps.Clone(s.PendingOperations) |
| 49 | for id, op := range s.PendingOperations { |
| 50 | op.Request, op.Result = bytes.Clone(op.Request), bytes.Clone(op.Result) |
| 51 | op.SessionIDs, op.Dependencies = slices.Clone(op.SessionIDs), slices.Clone(op.Dependencies) |
| 52 | op.extra = cloneUnknownFields(op.extra) |
| 53 | op.Presentation = clonePresentation(op.Presentation) |
| 54 | if op.Mapping != nil { |
| 55 | m := cloneSourceMapping(*op.Mapping) |
| 56 | op.Mapping = &m |
| 57 | } |
| 58 | s.PendingOperations[id] = op |
| 59 | } |
| 60 | s.RecoveryEntries = maps.Clone(s.RecoveryEntries) |
| 61 | for id, entry := range s.RecoveryEntries { |
| 62 | entry.extra = cloneUnknownFields(entry.extra) |
| 63 | s.RecoveryEntries[id] = entry |
| 64 | } |
| 65 | s.Presentation = maps.Clone(s.Presentation) |
| 66 | for id, p := range s.Presentation { |
| 67 | p.extra = cloneUnknownFields(p.extra) |
| 68 | s.Presentation[id] = p |
| 69 | } |
| 70 | return s |
| 71 | } |
| 72 | |
| 73 | func cloneSourceMapping(m SourceMapping) SourceMapping { |
| 74 | m.RetainedArtifacts = slices.Clone(m.RetainedArtifacts) |
| 75 | m.extra = cloneUnknownFields(m.extra) |
| 76 | return m |
| 77 | } |
| 78 | |
| 79 | func clonePresentation(p *Presentation) *Presentation { |
| 80 | if p == nil { |
| 81 | return nil |
| 82 | } |
| 83 | copy := *p |
| 84 | copy.extra = cloneUnknownFields(p.extra) |
| 85 | return © |
| 86 | } |
| 87 |