func validateCSV(s *testSuite, l types.List) { s.Equal(uint64(100), l.Len()) i := uint64(0) l.IterAll(func(v types.Value, j uint64) { s.Equal(i, j) st := v.(types.Struct) s.Equal(types.String(fmt.Sprintf("a%d", i)), st.Get("a")) s.Equal(types.Number(i), st.Get("b")) i++ }) }
// Write takes a types.List l of structs (described by sd) and writes it to output as comma-delineated values. func Write(l types.List, sd types.StructDesc, comma rune, output io.Writer) { structChan := make(chan types.Struct, 1024) go func() { l.IterAll(func(v types.Value, index uint64) { structChan <- v.(types.Struct) }) close(structChan) }() fieldNames := getFieldNamesFromStruct(sd) csvWriter := csv.NewWriter(output) csvWriter.Comma = comma d.Exp.NoError(csvWriter.Write(fieldNames), "Failed to write header %v", fieldNames) record := make([]string, len(fieldNames)) for s := range structChan { for i, f := range fieldNames { record[i] = fmt.Sprintf("%v", s.Get(f)) } d.Exp.NoError(csvWriter.Write(record), "Failed to write record %v", record) } csvWriter.Flush() d.Exp.NoError(csvWriter.Error(), "error flushing csv") }
func diffSummaryList(ch chan<- diffSummaryProgress, v1, v2 types.List) { ch <- diffSummaryProgress{OldSize: v1.Len(), NewSize: v2.Len()} spliceChan := make(chan types.Splice) stopChan := make(chan struct{}, 1) // buffer size of 1, so this won't block if diff already finished go func() { v2.Diff(v1, spliceChan, stopChan) close(spliceChan) }() for splice := range spliceChan { if splice.SpRemoved == splice.SpAdded { ch <- diffSummaryProgress{Changes: splice.SpRemoved} } else { ch <- diffSummaryProgress{Adds: splice.SpAdded, Removes: splice.SpRemoved} } } }
func diffLists(dq *diffQueue, w io.Writer, p types.Path, v1, v2 types.List) { wroteHeader := false splices := v2.Diff(v1) for _, splice := range splices { if splice.SpRemoved == splice.SpAdded { for i := uint64(0); i < splice.SpRemoved; i++ { lastEl := v1.Get(splice.SpAt + i) newEl := v2.Get(splice.SpFrom + i) if canCompare(lastEl, newEl) { idx := types.Number(splice.SpAt + i) p1 := p.AddIndex(idx) dq.PushBack(diffInfo{p1, idx, lastEl, newEl}) } else { wroteHeader = writeHeader(w, wroteHeader, p) line(w, subPrefix, nil, v1.Get(splice.SpAt+i)) line(w, addPrefix, nil, v2.Get(splice.SpFrom+i)) } } } else { for i := uint64(0); i < splice.SpRemoved; i++ { wroteHeader = writeHeader(w, wroteHeader, p) line(w, subPrefix, nil, v1.Get(splice.SpAt+i)) } for i := uint64(0); i < splice.SpAdded; i++ { wroteHeader = writeHeader(w, wroteHeader, p) line(w, addPrefix, nil, v2.Get(splice.SpFrom+i)) } } } writeFooter(w, wroteHeader) }
func diffLists(w io.Writer, p types.Path, v1, v2 types.List) (err error) { spliceChan := make(chan types.Splice) stopChan := make(chan struct{}, 1) // buffer size of 1, so this won't block if diff already finished go func() { v2.Diff(v1, spliceChan, stopChan) close(spliceChan) }() wroteHdr := false for splice := range spliceChan { if err != nil { break } if splice.SpRemoved == splice.SpAdded { // Heuristic: list only has modifications. for i := uint64(0); i < splice.SpRemoved; i++ { lastEl := v1.Get(splice.SpAt + i) newEl := v2.Get(splice.SpFrom + i) if shouldDescend(lastEl, newEl) { idx := types.Number(splice.SpAt + i) writeFooter(w, &wroteHdr) err = diff(w, p.AddIndex(idx), idx, lastEl, newEl) } else { writeHeader(w, p, &wroteHdr) line(w, DEL, nil, v1.Get(splice.SpAt+i)) err = line(w, ADD, nil, v2.Get(splice.SpFrom+i)) } } continue } // Heuristic: list only has additions/removals. for i := uint64(0); i < splice.SpRemoved && err == nil; i++ { writeHeader(w, p, &wroteHdr) err = line(w, DEL, nil, v1.Get(splice.SpAt+i)) } for i := uint64(0); i < splice.SpAdded && err == nil; i++ { writeHeader(w, p, &wroteHdr) err = line(w, ADD, nil, v2.Get(splice.SpFrom+i)) } } err = writeFooter(w, &wroteHdr) if err != nil { stopChan <- struct{}{} // Wait for diff to stop. for range spliceChan { } } return }
func diffLists(w io.Writer, p types.Path, v1, v2 types.List) { spliceChan := make(chan types.Splice) stopChan := make(chan struct{}, 1) // buffer size of 1, so this won't block if diff already finished defer stop(stopChan) go func() { v2.Diff(v1, spliceChan, stopChan) close(spliceChan) }() wroteHeader := false for splice := range spliceChan { if splice.SpRemoved == splice.SpAdded { for i := uint64(0); i < splice.SpRemoved; i++ { lastEl := v1.Get(splice.SpAt + i) newEl := v2.Get(splice.SpFrom + i) if shouldDescend(lastEl, newEl) { idx := types.Number(splice.SpAt + i) diff(w, p.AddIndex(idx), idx, lastEl, newEl) } else { wroteHeader = writeHeader(w, wroteHeader, p) line(w, DEL, nil, v1.Get(splice.SpAt+i)) line(w, ADD, nil, v2.Get(splice.SpFrom+i)) } } } else { for i := uint64(0); i < splice.SpRemoved; i++ { wroteHeader = writeHeader(w, wroteHeader, p) line(w, DEL, nil, v1.Get(splice.SpAt+i)) } for i := uint64(0); i < splice.SpAdded; i++ { wroteHeader = writeHeader(w, wroteHeader, p) line(w, ADD, nil, v2.Get(splice.SpFrom+i)) } } } writeFooter(w, wroteHeader) }