1 #include "dynamic_depth/item.h"
2
3 #include "android-base/logging.h"
4 #include "dynamic_depth/const.h"
5
6 using ::dynamic_depth::xmpmeta::xml::Deserializer;
7 using ::dynamic_depth::xmpmeta::xml::Serializer;
8
9 namespace dynamic_depth {
10 namespace {
11
12 constexpr char kNamespaceHref[] = "http://ns.google.com/photos/dd/1.0/item/";
13
14 constexpr char kMime[] = "Mime";
15 constexpr char kLength[] = "Length";
16 constexpr char kPadding[] = "Padding";
17 constexpr char kDataUri[] = "DataURI";
18
19 } // namespace
20
21 // Private constructor.
Item(const ItemParams & params)22 Item::Item(const ItemParams& params) : params_(params) {}
23
24 // Private instantiator.
25
FromDataInternal(const ItemParams & params,bool check_filepath)26 std::unique_ptr<Item> Item::FromDataInternal(const ItemParams& params,
27 bool check_filepath) {
28 if (check_filepath && params.length != params.payload_to_serialize.size()) {
29 LOG(ERROR) << "Length does not match payload's size";
30 return nullptr;
31 }
32
33 if (params.mime.empty()) {
34 LOG(ERROR) << "Mime is empty";
35 return nullptr;
36 }
37
38 if (params.length < 0) {
39 LOG(ERROR) << "Item length must be non-negative";
40 return nullptr;
41 }
42
43 if (params.padding > 0 &&
44 static_cast<int>(params.length - params.padding) <= 0) {
45 LOG(ERROR) << "Item length must be larger than padding; found padding="
46 << params.padding << ", length=" << params.length;
47 return nullptr;
48 }
49
50 // TODO(miraleung): Check for only supported mime types?
51
52 return std::unique_ptr<Item>(new Item(params)); // NOLINT
53 }
54
GetNamespaces(std::unordered_map<string,string> * ns_name_href_map)55 void Item::GetNamespaces(std::unordered_map<string, string>* ns_name_href_map) {
56 if (ns_name_href_map == nullptr) {
57 LOG(ERROR) << "Namespace list or own namespace is null";
58 return;
59 }
60
61 ns_name_href_map->emplace(DynamicDepthConst::Item(), kNamespaceHref);
62 }
63
FromData(const ItemParams & params)64 std::unique_ptr<Item> Item::FromData(const ItemParams& params) {
65 return FromDataInternal(params, true);
66 }
67
FromDeserializer(const Deserializer & parent_deserializer)68 std::unique_ptr<Item> Item::FromDeserializer(
69 const Deserializer& parent_deserializer) {
70 std::unique_ptr<Deserializer> deserializer =
71 parent_deserializer.CreateDeserializer(
72 DynamicDepthConst::Namespace(DynamicDepthConst::Item()),
73 DynamicDepthConst::Item());
74 if (deserializer == nullptr) {
75 return nullptr;
76 }
77
78 string mime;
79 int length;
80 int padding = 0;
81 string data_uri;
82
83 if (!deserializer->ParseString(DynamicDepthConst::Item(), kMime, &mime) ||
84 !deserializer->ParseInt(DynamicDepthConst::Item(), kLength, &length)) {
85 return nullptr;
86 }
87
88 deserializer->ParseInt(DynamicDepthConst::Item(), kPadding, &padding);
89 deserializer->ParseString(DynamicDepthConst::Item(), kDataUri, &data_uri);
90
91 ItemParams params(mime, length);
92 if (!data_uri.empty()) {
93 params.data_uri = data_uri;
94 }
95 if (padding > 0) {
96 params.padding = padding;
97 }
98
99 return Item::FromDataInternal(params, false);
100 }
101
102 // Getters.
GetMime() const103 const string& Item::GetMime() const { return params_.mime; }
GetLength() const104 unsigned int Item::GetLength() const { return params_.length; }
GetDataUri() const105 const string& Item::GetDataUri() const { return params_.data_uri; }
GetPadding() const106 unsigned int Item::GetPadding() const { return params_.padding; }
GetPayloadToSerialize() const107 const string& Item::GetPayloadToSerialize() const {
108 return params_.payload_to_serialize;
109 }
110
Serialize(Serializer * serializer) const111 bool Item::Serialize(Serializer* serializer) const {
112 if (serializer == nullptr) {
113 LOG(ERROR) << "Serializer is null";
114 return false;
115 }
116
117 // No error-checking for the mime or length here, since it's assumed to be
118 // taken care of in the instantiator.
119 bool success = serializer->WriteProperty(DynamicDepthConst::Item(), kMime,
120 params_.mime) &&
121 serializer->WriteProperty(DynamicDepthConst::Item(), kLength,
122 std::to_string(params_.length));
123 if (!params_.data_uri.empty()) {
124 success &= serializer->WriteProperty(DynamicDepthConst::Item(), kDataUri,
125 params_.data_uri);
126 }
127
128 if (params_.padding > 0) {
129 success &= serializer->WriteProperty(DynamicDepthConst::Item(), kPadding,
130 std::to_string(params_.padding));
131 }
132
133 return success;
134 }
135
136 } // namespace dynamic_depth
137