Add line breaks to make dehydrated files more merge-friendly.

Change-Id: Ica329608e5ee7f873a55dc27e6c14bb8734665a3
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/324118
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Ethan Nicholas <ethannicholas@google.com>
diff --git a/src/sksl/SkSLDehydrator.cpp b/src/sksl/SkSLDehydrator.cpp
index 3896526..5689fa9 100644
--- a/src/sksl/SkSLDehydrator.cpp
+++ b/src/sksl/SkSLDehydrator.cpp
@@ -62,7 +62,7 @@
         if (symbols) {
             dehydrator->write(*symbols);
         } else {
-            dehydrator->writeU8(Rehydrator::kVoid_Command);
+            dehydrator->writeCommand(Rehydrator::kVoid_Command);
         }
     }
 
@@ -76,12 +76,12 @@
 
 void Dehydrator::write(Layout l) {
     if (l == Layout()) {
-        this->writeU8(Rehydrator::kDefaultLayout_Command);
+        this->writeCommand(Rehydrator::kDefaultLayout_Command);
     } else if (l == Layout::builtin(l.fBuiltin)) {
-        this->writeS8(Rehydrator::kBuiltinLayout_Command);
+        this->writeCommand(Rehydrator::kBuiltinLayout_Command);
         this->writeS16(l.fBuiltin);
     } else {
-        this->writeS8(Rehydrator::kLayout_Command);
+        this->writeCommand(Rehydrator::kLayout_Command);
         fBody.write32(l.fFlags);
         this->writeS8(l.fLocation);
         this->writeS8(l.fOffset);
@@ -103,14 +103,14 @@
 
 void Dehydrator::write(Modifiers m) {
     if (m == Modifiers()) {
-        this->writeU8(Rehydrator::kDefaultModifiers_Command);
+        this->writeCommand(Rehydrator::kDefaultModifiers_Command);
     } else {
         if (m.fFlags <= 255) {
-            this->writeU8(Rehydrator::kModifiers8Bit_Command);
+            this->writeCommand(Rehydrator::kModifiers8Bit_Command);
             this->write(m.fLayout);
             this->writeU8(m.fFlags);
         } else {
-            this->writeU8(Rehydrator::kModifiers_Command);
+            this->writeCommand(Rehydrator::kModifiers_Command);
             this->write(m.fLayout);
             this->writeS32(m.fFlags);
         }
@@ -128,6 +128,7 @@
         offset = fStringBuffer.str().length() + HEADER_SIZE;
         fStrings.insert({ s, offset });
         SkASSERT(s.length() <= 255);
+        fStringBreaks.add(fStringBuffer.bytesWritten());
         fStringBuffer.write8(s.length());
         fStringBuffer.writeString(s);
     } else {
@@ -139,14 +140,14 @@
 void Dehydrator::write(const Symbol& s) {
     uint16_t id = this->symbolId(&s, false);
     if (id) {
-        this->writeU8(Rehydrator::kSymbolRef_Command);
+        this->writeCommand(Rehydrator::kSymbolRef_Command);
         this->writeU16(id);
         return;
     }
     switch (s.kind()) {
         case Symbol::Kind::kFunctionDeclaration: {
             const FunctionDeclaration& f = s.as<FunctionDeclaration>();
-            this->writeU8(Rehydrator::kFunctionDeclaration_Command);
+            this->writeCommand(Rehydrator::kFunctionDeclaration_Command);
             this->writeId(&f);
             this->write(f.modifiers());
             this->write(f.name());
@@ -159,7 +160,7 @@
         }
         case Symbol::Kind::kSymbolAlias: {
             const SymbolAlias& alias = s.as<SymbolAlias>();
-            this->writeU8(Rehydrator::kSymbolAlias_Command);
+            this->writeCommand(Rehydrator::kSymbolAlias_Command);
             this->writeId(&alias);
             this->write(alias.name());
             this->write(*alias.origSymbol());
@@ -167,7 +168,7 @@
         }
         case Symbol::Kind::kUnresolvedFunction: {
             const UnresolvedFunction& f = s.as<UnresolvedFunction>();
-            this->writeU8(Rehydrator::kUnresolvedFunction_Command);
+            this->writeCommand(Rehydrator::kUnresolvedFunction_Command);
             this->writeId(&f);
             this->writeU8(f.fFunctions.size());
             for (const FunctionDeclaration* funcDecl : f.fFunctions) {
@@ -179,23 +180,23 @@
             const Type& t = s.as<Type>();
             switch (t.typeKind()) {
                 case Type::TypeKind::kArray:
-                    this->writeU8(Rehydrator::kArrayType_Command);
+                    this->writeCommand(Rehydrator::kArrayType_Command);
                     this->writeId(&t);
                     this->write(t.componentType());
                     this->writeS8(t.columns());
                     break;
                 case Type::TypeKind::kEnum:
-                    this->writeU8(Rehydrator::kEnumType_Command);
+                    this->writeCommand(Rehydrator::kEnumType_Command);
                     this->writeId(&t);
                     this->write(t.name());
                     break;
                 case Type::TypeKind::kNullable:
-                    this->writeU8(Rehydrator::kNullableType_Command);
+                    this->writeCommand(Rehydrator::kNullableType_Command);
                     this->writeId(&t);
                     this->write(t.componentType());
                     break;
                 case Type::TypeKind::kStruct:
-                    this->writeU8(Rehydrator::kStructType_Command);
+                    this->writeCommand(Rehydrator::kStructType_Command);
                     this->writeId(&t);
                     this->write(t.name());
                     this->writeU8(t.fields().size());
@@ -206,7 +207,7 @@
                     }
                     break;
                 default:
-                    this->writeU8(Rehydrator::kSystemType_Command);
+                    this->writeCommand(Rehydrator::kSystemType_Command);
                     this->writeId(&t);
                     this->write(t.name());
             }
@@ -214,7 +215,7 @@
         }
         case Symbol::Kind::kVariable: {
             const Variable& v = s.as<Variable>();
-            this->writeU8(Rehydrator::kVariable_Command);
+            this->writeCommand(Rehydrator::kVariable_Command);
             this->writeId(&v);
             this->write(v.modifiers());
             this->write(v.name());
@@ -224,7 +225,7 @@
         }
         case Symbol::Kind::kField: {
             const Field& f = s.as<Field>();
-            this->writeU8(Rehydrator::kField_Command);
+            this->writeCommand(Rehydrator::kField_Command);
             this->writeU16(this->symbolId(&f.owner()));
             this->writeU8(f.fieldIndex());
             break;
@@ -236,7 +237,7 @@
 }
 
 void Dehydrator::write(const SymbolTable& symbols) {
-    this->writeU8(Rehydrator::kSymbolTable_Command);
+    this->writeCommand(Rehydrator::kSymbolTable_Command);
     this->writeU16(symbols.fOwnedSymbols.size());
     for (const std::unique_ptr<const Symbol>& s : symbols.fOwnedSymbols) {
         this->write(*s);
@@ -250,6 +251,7 @@
         bool found = false;
         for (size_t i = 0; i < symbols.fOwnedSymbols.size(); ++i) {
             if (symbols.fOwnedSymbols[i].get() == p.second) {
+                fCommandBreaks.add(fBody.bytesWritten());
                 this->writeU16(i);
                 found = true;
                 break;
@@ -264,7 +266,7 @@
         switch (e->kind()) {
             case Expression::Kind::kBinary: {
                 const BinaryExpression& b = e->as<BinaryExpression>();
-                this->writeU8(Rehydrator::kBinary_Command);
+                this->writeCommand(Rehydrator::kBinary_Command);
                 this->write(&b.left());
                 this->writeU8((int) b.getOperator());
                 this->write(&b.right());
@@ -273,13 +275,13 @@
             }
             case Expression::Kind::kBoolLiteral: {
                 const BoolLiteral& b = e->as<BoolLiteral>();
-                this->writeU8(Rehydrator::kBoolLiteral_Command);
+                this->writeCommand(Rehydrator::kBoolLiteral_Command);
                 this->writeU8(b.value());
                 break;
             }
             case Expression::Kind::kConstructor: {
                 const Constructor& c = e->as<Constructor>();
-                this->writeU8(Rehydrator::kConstructor_Command);
+                this->writeCommand(Rehydrator::kConstructor_Command);
                 this->write(c.type());
                 this->writeU8(c.arguments().size());
                 for (const auto& a : c.arguments()) {
@@ -289,13 +291,11 @@
             }
             case Expression::Kind::kExternalFunctionCall:
             case Expression::Kind::kExternalValue:
-                // not implemented; doesn't seem like we'll ever need them from within an include
-                // file
-                SkASSERT(false);
+                SkDEBUGFAIL("unimplemented--not expected to be used from within an include file");
                 break;
             case Expression::Kind::kFieldAccess: {
                 const FieldAccess& f = e->as<FieldAccess>();
-                this->writeU8(Rehydrator::kFieldAccess_Command);
+                this->writeCommand(Rehydrator::kFieldAccess_Command);
                 this->write(f.fBase.get());
                 this->writeU8(f.fFieldIndex);
                 this->writeU8(f.fOwnerKind);
@@ -303,7 +303,7 @@
             }
             case Expression::Kind::kFloatLiteral: {
                 const FloatLiteral& f = e->as<FloatLiteral>();
-                this->writeU8(Rehydrator::kFloatLiteral_Command);
+                this->writeCommand(Rehydrator::kFloatLiteral_Command);
                 FloatIntUnion u;
                 u.fFloat = f.value();
                 this->writeS32(u.fInt);
@@ -311,7 +311,7 @@
             }
             case Expression::Kind::kFunctionCall: {
                 const FunctionCall& f = e->as<FunctionCall>();
-                this->writeU8(Rehydrator::kFunctionCall_Command);
+                this->writeCommand(Rehydrator::kFunctionCall_Command);
                 this->write(f.type());
                 this->writeId(&f.function());
                 this->writeU8(f.arguments().size());
@@ -322,44 +322,44 @@
             }
             case Expression::Kind::kIndex: {
                 const IndexExpression& i = e->as<IndexExpression>();
-                this->writeU8(Rehydrator::kIndex_Command);
+                this->writeCommand(Rehydrator::kIndex_Command);
                 this->write(i.fBase.get());
                 this->write(i.fIndex.get());
                 break;
             }
             case Expression::Kind::kIntLiteral: {
                 const IntLiteral& i = e->as<IntLiteral>();
-                this->writeU8(Rehydrator::kIntLiteral_Command);
+                this->writeCommand(Rehydrator::kIntLiteral_Command);
                 this->writeS32(i.value());
                 break;
             }
             case Expression::Kind::kNullLiteral:
-                this->writeU8(Rehydrator::kNullLiteral_Command);
+                this->writeCommand(Rehydrator::kNullLiteral_Command);
                 break;
             case Expression::Kind::kPostfix: {
                 const PostfixExpression& p = e->as<PostfixExpression>();
-                this->writeU8(Rehydrator::kPostfix_Command);
+                this->writeCommand(Rehydrator::kPostfix_Command);
                 this->writeU8((int) p.fOperator);
                 this->write(p.fOperand.get());
                 break;
             }
             case Expression::Kind::kPrefix: {
                 const PrefixExpression& p = e->as<PrefixExpression>();
-                this->writeU8(Rehydrator::kPrefix_Command);
+                this->writeCommand(Rehydrator::kPrefix_Command);
                 this->writeU8((int) p.fOperator);
                 this->write(p.fOperand.get());
                 break;
             }
             case Expression::Kind::kSetting: {
                 const Setting& s = e->as<Setting>();
-                this->writeU8(Rehydrator::kSetting_Command);
+                this->writeCommand(Rehydrator::kSetting_Command);
                 this->write(s.name());
                 this->write(s.type());
                 break;
             }
             case Expression::Kind::kSwizzle: {
                 const Swizzle& s = e->as<Swizzle>();
-                this->writeU8(Rehydrator::kSwizzle_Command);
+                this->writeCommand(Rehydrator::kSwizzle_Command);
                 this->write(s.fBase.get());
                 this->writeU8(s.fComponents.size());
                 for (int c : s.fComponents) {
@@ -369,7 +369,7 @@
             }
             case Expression::Kind::kTernary: {
                 const TernaryExpression& t = e->as<TernaryExpression>();
-                this->writeU8(Rehydrator::kTernary_Command);
+                this->writeCommand(Rehydrator::kTernary_Command);
                 this->write(t.test().get());
                 this->write(t.ifTrue().get());
                 this->write(t.ifFalse().get());
@@ -377,7 +377,7 @@
             }
             case Expression::Kind::kVariableReference: {
                 const VariableReference& v = e->as<VariableReference>();
-                this->writeU8(Rehydrator::kVariableReference_Command);
+                this->writeCommand(Rehydrator::kVariableReference_Command);
                 this->writeId(v.variable());
                 this->writeU8(v.refKind());
                 break;
@@ -385,12 +385,11 @@
             case Expression::Kind::kFunctionReference:
             case Expression::Kind::kTypeReference:
             case Expression::Kind::kDefined:
-                // shouldn't appear in finished code
-                SkASSERT(false);
+                SkDEBUGFAIL("this expression shouldn't appear in finished code");
                 break;
         }
     } else {
-        this->writeU8(Rehydrator::kVoid_Command);
+        this->writeCommand(Rehydrator::kVoid_Command);
     }
 }
 
@@ -399,7 +398,7 @@
         switch (s->kind()) {
             case Statement::Kind::kBlock: {
                 const Block& b = s->as<Block>();
-                this->writeU8(Rehydrator::kBlock_Command);
+                this->writeCommand(Rehydrator::kBlock_Command);
                 AutoDehydratorSymbolTable symbols(this, b.symbolTable());
                 this->writeU8(b.children().size());
                 for (const std::unique_ptr<Statement>& blockStmt : b.children()) {
@@ -409,30 +408,30 @@
                 break;
             }
             case Statement::Kind::kBreak:
-                this->writeU8(Rehydrator::kBreak_Command);
+                this->writeCommand(Rehydrator::kBreak_Command);
                 break;
             case Statement::Kind::kContinue:
-                this->writeU8(Rehydrator::kContinue_Command);
+                this->writeCommand(Rehydrator::kContinue_Command);
                 break;
             case Statement::Kind::kDiscard:
-                this->writeU8(Rehydrator::kDiscard_Command);
+                this->writeCommand(Rehydrator::kDiscard_Command);
                 break;
             case Statement::Kind::kDo: {
                 const DoStatement& d = s->as<DoStatement>();
-                this->writeU8(Rehydrator::kDo_Command);
+                this->writeCommand(Rehydrator::kDo_Command);
                 this->write(d.statement().get());
                 this->write(d.test().get());
                 break;
             }
             case Statement::Kind::kExpression: {
                 const ExpressionStatement& e = s->as<ExpressionStatement>();
-                this->writeU8(Rehydrator::kExpressionStatement_Command);
+                this->writeCommand(Rehydrator::kExpressionStatement_Command);
                 this->write(e.expression().get());
                 break;
             }
             case Statement::Kind::kFor: {
                 const ForStatement& f = s->as<ForStatement>();
-                this->writeU8(Rehydrator::kFor_Command);
+                this->writeCommand(Rehydrator::kFor_Command);
                 this->write(f.initializer().get());
                 this->write(f.test().get());
                 this->write(f.next().get());
@@ -442,7 +441,7 @@
             }
             case Statement::Kind::kIf: {
                 const IfStatement& i = s->as<IfStatement>();
-                this->writeU8(Rehydrator::kIf_Command);
+                this->writeCommand(Rehydrator::kIf_Command);
                 this->writeU8(i.isStatic());
                 this->write(i.test().get());
                 this->write(i.ifTrue().get());
@@ -451,22 +450,22 @@
             }
             case Statement::Kind::kInlineMarker: {
                 const InlineMarker& i = s->as<InlineMarker>();
-                this->writeU8(Rehydrator::kInlineMarker_Command);
+                this->writeCommand(Rehydrator::kInlineMarker_Command);
                 this->writeId(i.fFuncDecl);
                 break;
             }
             case Statement::Kind::kNop:
-                SkASSERT(false);
+                SkDEBUGFAIL("unexpected--nop statement in finished code");
                 break;
             case Statement::Kind::kReturn: {
                 const ReturnStatement& r = s->as<ReturnStatement>();
-                this->writeU8(Rehydrator::kReturn_Command);
+                this->writeCommand(Rehydrator::kReturn_Command);
                 this->write(r.fExpression.get());
                 break;
             }
             case Statement::Kind::kSwitch: {
                 const SwitchStatement& ss = s->as<SwitchStatement>();
-                this->writeU8(Rehydrator::kSwitch_Command);
+                this->writeCommand(Rehydrator::kSwitch_Command);
                 this->writeU8(ss.fIsStatic);
                 AutoDehydratorSymbolTable symbols(this, ss.fSymbols);
                 this->write(ss.fValue.get());
@@ -481,11 +480,11 @@
                 break;
             }
             case Statement::Kind::kSwitchCase:
-                SkASSERT(false);
+                SkDEBUGFAIL("SwitchCase statements shouldn't appear here");
                 break;
             case Statement::Kind::kVarDeclaration: {
                 const VarDeclaration& v = s->as<VarDeclaration>();
-                this->writeU8(Rehydrator::kVarDeclaration_Command);
+                this->writeCommand(Rehydrator::kVarDeclaration_Command);
                 this->writeU16(this->symbolId(v.fVar));
                 this->write(v.fBaseType);
                 this->writeU8(v.fSizes.size());
@@ -497,14 +496,14 @@
             }
             case Statement::Kind::kWhile: {
                 const WhileStatement& w = s->as<WhileStatement>();
-                this->writeU8(Rehydrator::kWhile_Command);
+                this->writeCommand(Rehydrator::kWhile_Command);
                 this->write(w.fTest.get());
                 this->write(w.fStatement.get());
                 break;
             }
         }
     } else {
-        this->writeU8(Rehydrator::kVoid_Command);
+        this->writeCommand(Rehydrator::kVoid_Command);
     }
 }
 
@@ -512,7 +511,7 @@
     switch (e.kind()) {
         case ProgramElement::Kind::kEnum: {
             const Enum& en = e.as<Enum>();
-            this->writeU8(Rehydrator::kEnum_Command);
+            this->writeCommand(Rehydrator::kEnum_Command);
             this->write(en.typeName());
             AutoDehydratorSymbolTable symbols(this, en.symbols());
             for (const std::unique_ptr<const Symbol>& s : en.symbols()->fOwnedSymbols) {
@@ -529,7 +528,7 @@
             break;
         case ProgramElement::Kind::kFunction: {
             const FunctionDefinition& f = e.as<FunctionDefinition>();
-            this->writeU8(Rehydrator::kFunctionDefinition_Command);
+            this->writeCommand(Rehydrator::kFunctionDefinition_Command);
             this->writeU16(this->symbolId(&f.fDeclaration));
             this->write(f.fBody.get());
             this->writeU8(f.fReferencedIntrinsics.size());
@@ -544,7 +543,7 @@
         }
         case ProgramElement::Kind::kInterfaceBlock: {
             const InterfaceBlock& i = e.as<InterfaceBlock>();
-            this->writeU8(Rehydrator::kInterfaceBlock_Command);
+            this->writeCommand(Rehydrator::kInterfaceBlock_Command);
             this->write(*i.fVariable);
             this->write(i.fTypeName);
             this->write(i.fInstanceName);
@@ -562,7 +561,7 @@
             break;
         case ProgramElement::Kind::kGlobalVar: {
             const GlobalVarDeclaration& v = e.as<GlobalVarDeclaration>();
-            this->writeU8(Rehydrator::kVarDeclarations_Command);
+            this->writeCommand(Rehydrator::kVarDeclarations_Command);
             this->write(v.fDecl.get());
             break;
         }
@@ -570,7 +569,7 @@
 }
 
 void Dehydrator::write(const std::vector<std::unique_ptr<ProgramElement>>& elements) {
-    this->writeU8(Rehydrator::kElements_Command);
+    this->writeCommand(Rehydrator::kElements_Command);
     this->writeU8(elements.size());
     for (const auto& e : elements) {
         this->write(*e);
@@ -578,9 +577,24 @@
 }
 
 void Dehydrator::finish(OutputStream& out) {
+    String stringBuffer = fStringBuffer.str();
+    String commandBuffer = fBody.str();
+
     out.write16(fStringBuffer.str().size());
-    out.writeString(fStringBuffer.str());
-    out.writeString(fBody.str());
+    fStringBufferStart = 2;
+    out.writeString(stringBuffer);
+    fCommandStart = fStringBufferStart + stringBuffer.size();
+    out.writeString(commandBuffer);
+}
+
+const char* Dehydrator::prefixAtOffset(size_t byte) {
+    if (byte >= fCommandStart) {
+        return fCommandBreaks.contains(byte - fCommandStart) ? "\n" : "";
+    }
+    if (byte >= fStringBufferStart) {
+        return fStringBreaks.contains(byte - fStringBufferStart) ? "\n" : "";
+    }
+    return "";
 }
 
 } // namespace