[storage][volume_image]: address_descriptor Schema

Defined schema to support address_descriptor for
fvm mappings.

TEST=JSON validator.

Change-Id: Ie4272713b5fee45d00eda2c84e0ecd0fb50b32b4
Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/373061
Commit-Queue: Gianfranco Valentino <gevalentino@google.com>
Testability-Review: Gianfranco Valentino <gevalentino@google.com>
Reviewed-by: Richard Chen <tianruichen@google.com>
diff --git a/src/storage/volume_image/BUILD.gn b/src/storage/volume_image/BUILD.gn
index 7aa1b1c..2dd7cc1 100644
--- a/src/storage/volume_image/BUILD.gn
+++ b/src/storage/volume_image/BUILD.gn
@@ -68,6 +68,11 @@
               "//src/storage/volume_image/serialization/volume_descriptor.schema.json")
       dest = "schema/volume_descriptor.schema.json"
     },
+    {
+      path = rebase_path(
+              "//src/storage/volume_image/serialization/address_descriptor.schema.json")
+      dest = "schema/address_descriptor.schema.json"
+    },
   ]
 }
 
diff --git a/src/storage/volume_image/fvm/address_descriptor.h b/src/storage/volume_image/fvm/address_descriptor.h
index e1c1617..e4ff760 100644
--- a/src/storage/volume_image/fvm/address_descriptor.h
+++ b/src/storage/volume_image/fvm/address_descriptor.h
@@ -8,28 +8,28 @@
 #include <lib/fit/result.h>
 
 #include <cstdint>
+#include <map>
+#include <string>
 #include <vector>
 
 #include <fbl/span.h>
 
 namespace storage::volume_image {
 
-struct AddressSpace {
-  // Where the address space begins.
-  uint64_t offset;
-
-  // Number of addressable blocks in this address space.
-  uint64_t count;
-};
-
 // Describes a mapping from an address space in a source format, into a target space.
 // The target space is the fvm virtual address space that each partition has.
 struct AddressMap {
   // Original address space, where data is read from.
-  AddressSpace source;
+  uint64_t source;
 
   // Target address space, where data is written to, in the fvm image.
-  AddressSpace target;
+  uint64_t target;
+
+  // Number of addressable blocks in this address space.
+  uint64_t count;
+
+  // Options that apply to this mapping.
+  std::map<std::string, uint64_t> options;
 };
 
 // Represents how the input partition image, should be transformed to fit in the fvm.
@@ -37,12 +37,13 @@
   // Returns an |AddressDescriptor| containing the deserialized contents from |serialized|.
   //
   // On error, returns a string describing the error condition.
-  static fit::result<AddressDescriptor, std::string> Deserialize(fbl::Span<uint8_t> serialized);
+  static fit::result<AddressDescriptor, std::string> Deserialize(
+      fbl::Span<const uint8_t> serialized);
 
   // Returns a vector containing a serialized version of |this|.
   //
   // On error, returns a string describing the error condition.
-  fit::result<std::vector<uint8_t>, std::string> Serialize();
+  fit::result<std::vector<uint8_t>, std::string> Serialize() const;
 
   // List of mappings.
   std::vector<AddressMap> mappings;
diff --git a/src/storage/volume_image/serialization/BUILD.gn b/src/storage/volume_image/serialization/BUILD.gn
index 5eee566..3ccac6f 100644
--- a/src/storage/volume_image/serialization/BUILD.gn
+++ b/src/storage/volume_image/serialization/BUILD.gn
@@ -11,7 +11,10 @@
 }
 
 copy("schema_json") {
-  sources = [ "volume_descriptor.schema.json" ]
+  sources = [
+    "address_descriptor.schema.json",
+    "volume_descriptor.schema.json",
+  ]
   outputs = [ "$root_out_dir/schema/{{source_file_part}}" ]
 }
 
diff --git a/src/storage/volume_image/serialization/address_descriptor.schema.json b/src/storage/volume_image/serialization/address_descriptor.schema.json
new file mode 100644
index 0000000..99d5fc8
--- /dev/null
+++ b/src/storage/volume_image/serialization/address_descriptor.schema.json
@@ -0,0 +1,56 @@
+{
+    "$schema": "http://json-schema.org/draft-07/schema#",
+    "title": "Volume Descriptor Serialized Format",
+    "description": "Configuration for processing a volume image.",
+    "definitions": {
+        "address_space": {
+            "type": "object",
+            "properties": {
+                "source": {
+                    "type": "integer",
+                    "minimum": 0
+                },
+                "target": {
+                    "type": "integer",
+                    "minimum": 0
+                },
+                "count": {
+                    "type": "integer",
+                    "minimum": 0
+                },
+                "options": {
+                    "type": "object",
+                    "additionalProperties": {
+                        "type": "integer",
+                        "minimum": 0
+                    }
+                }
+            },
+            "required": [
+                "source",
+                "target",
+                "count"
+            ]
+        },
+        "address_descriptor": {
+            "type": "object",
+            "properties": {
+                "magic": {
+                    "type": "integer",
+                    "minimum": 0
+                },
+                "mappings": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/address_map"
+                    }
+                }
+            },
+            "required": [
+                "magic",
+                "mappings"
+            ]
+        }
+    },
+    "$ref": "#/definitions/address_descriptor"
+}
\ No newline at end of file
diff --git a/src/storage/volume_image/serialization/schema.cc b/src/storage/volume_image/serialization/schema.cc
index fd5d49a..d5e5b70 100644
--- a/src/storage/volume_image/serialization/schema.cc
+++ b/src/storage/volume_image/serialization/schema.cc
@@ -21,6 +21,9 @@
     case Schema::kVolumeDescriptor:
       file.open(std::string(kPath).append("volume_descriptor.schema.json"));
       return std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
+    case Schema::kAddressDescriptor:
+      file.open(std::string(kPath).append("address_descriptor.schema.json"));
+      return std::string(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>());
     default:
       return std::string();
   }
diff --git a/src/storage/volume_image/serialization/schema.h b/src/storage/volume_image/serialization/schema.h
index 8352576..77c8d8e 100644
--- a/src/storage/volume_image/serialization/schema.h
+++ b/src/storage/volume_image/serialization/schema.h
@@ -12,6 +12,7 @@
 // Defines available schemas.
 enum Schema {
   kVolumeDescriptor,
+  kAddressDescriptor,
 };
 
 // Returns a string with the respective schema.
diff --git a/src/storage/volume_image/serialization/schema_test.cc b/src/storage/volume_image/serialization/schema_test.cc
index 537104c..b418583 100644
--- a/src/storage/volume_image/serialization/schema_test.cc
+++ b/src/storage/volume_image/serialization/schema_test.cc
@@ -20,5 +20,13 @@
   ASSERT_FALSE(parser.HasError()) << parser.error_str();
 }
 
+TEST(SchemaTest, AddressDescriptorSchemaIsValid) {
+  auto schema_json = GetSchema(Schema::kAddressDescriptor);
+
+  json_parser::JSONParser parser;
+  auto document = parser.ParseFromString(schema_json, "address_descriptor.schema.json");
+  ASSERT_FALSE(parser.HasError()) << parser.error_str();
+}
+
 }  // namespace
 }  // namespace storage::volume_image