UnmarshalWithXattrs unmarshals the provided raw document and xattr bytes when present. The provided DocumentUnmarshalLevel (unmarshalLevel) specifies how much of the provided document/xattr needs to be initially unmarshalled. If unmarshalLevel is anything less than the full document + metadata, th
(ctx context.Context, data, syncXattrData, hlvXattrData, revSeqNo []byte, globalSyncData []byte, unmarshalLevel DocumentUnmarshalLevel)
| 1224 | // lazy unmarshalling as needed. |
| 1225 | // Must handle cases where document body and hlvXattrData are present without syncXattrData for all DocumentUnmarshalLevel |
| 1226 | func (doc *Document) UnmarshalWithXattrs(ctx context.Context, data, syncXattrData, hlvXattrData, revSeqNo []byte, globalSyncData []byte, unmarshalLevel DocumentUnmarshalLevel) error { |
| 1227 | if doc.ID == "" { |
| 1228 | base.WarnfCtx(ctx, "Attempted to unmarshal document without ID set") |
| 1229 | return errors.New("Document was unmarshalled without ID set") |
| 1230 | } |
| 1231 | |
| 1232 | switch unmarshalLevel { |
| 1233 | case DocUnmarshalAll, DocUnmarshalSync: |
| 1234 | // Unmarshal full document and/or sync metadata. Documents written by XDCR may have HLV but no sync data |
| 1235 | doc.SyncData = SyncData{History: make(RevTree)} |
| 1236 | if syncXattrData != nil { |
| 1237 | unmarshalErr := base.JSONUnmarshal(syncXattrData, &doc.SyncData) |
| 1238 | if unmarshalErr != nil { |
| 1239 | return pkgerrors.WithStack(base.RedactErrorf("Failed to UnmarshalWithXattrs() doc with id: %s (DocUnmarshalAll/Sync). Error: %v", base.UD(doc.ID), unmarshalErr)) |
| 1240 | } |
| 1241 | } |
| 1242 | if hlvXattrData != nil { |
| 1243 | // parse the raw bytes of the hlv and convert deltas back to full values in memory |
| 1244 | err := base.JSONUnmarshal(hlvXattrData, &doc.HLV) |
| 1245 | if err != nil { |
| 1246 | return pkgerrors.WithStack(base.RedactErrorf("Failed to unmarshal HLV during UnmarshalWithXattrs() doc with id: %s (DocUnmarshalAll/Sync). Error: %v", base.UD(doc.ID), err)) |
| 1247 | } |
| 1248 | } |
| 1249 | if revSeqNo != nil { |
| 1250 | var err error |
| 1251 | doc.RevSeqNo, err = unmarshalRevSeqNo(revSeqNo) |
| 1252 | if err != nil { |
| 1253 | return pkgerrors.WithStack(base.RedactErrorf("Failed to unmarshal RevSeqNo during UnmarshalWithXattrs() doc with id: %s (DocUnmarshalAll/Sync). Error: %v", base.UD(doc.ID), err)) |
| 1254 | } |
| 1255 | } |
| 1256 | if len(globalSyncData) > 0 { |
| 1257 | if err := base.JSONUnmarshal(globalSyncData, &doc._globalSync); err != nil { |
| 1258 | base.WarnfCtx(ctx, "Failed to unmarshal globalSync xattr for key %v, globalSync will be ignored. Err: %v globalSync:%s", base.UD(doc.ID), err, globalSyncData) |
| 1259 | } |
| 1260 | } |
| 1261 | doc.SetAttachments(mergeAttachments(doc.SyncData.AttachmentsPre4dot0, doc.Attachments())) |
| 1262 | doc.SyncData.AttachmentsPre4dot0 = nil |
| 1263 | doc._rawBody = data |
| 1264 | // Unmarshal body if requested and present |
| 1265 | if unmarshalLevel == DocUnmarshalAll && len(data) > 0 { |
| 1266 | return doc._body.Unmarshal(data) |
| 1267 | } |
| 1268 | case DocUnmarshalNoHistory: |
| 1269 | // Unmarshal sync metadata only, excluding history |
| 1270 | doc.SyncData = SyncData{} |
| 1271 | if syncXattrData != nil { |
| 1272 | unmarshalErr := base.JSONUnmarshal(syncXattrData, &doc.SyncData) |
| 1273 | if unmarshalErr != nil { |
| 1274 | return pkgerrors.WithStack(base.RedactErrorf("Failed to UnmarshalWithXattrs() doc with id: %s (DocUnmarshalNoHistory). Error: %v", base.UD(doc.ID), unmarshalErr)) |
| 1275 | } |
| 1276 | } |
| 1277 | if hlvXattrData != nil { |
| 1278 | // parse the raw bytes of the hlv and convert deltas back to full values in memory |
| 1279 | err := base.JSONUnmarshal(hlvXattrData, &doc.HLV) |
| 1280 | if err != nil { |
| 1281 | return pkgerrors.WithStack(base.RedactErrorf("Failed to unmarshal HLV during UnmarshalWithXattrs() doc with id: %s (DocUnmarshalNoHistory). Error: %v", base.UD(doc.ID), err)) |
| 1282 | } |
| 1283 | } |