1 // Copyright 2017 The Draco Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //
15 #include "draco/metadata/metadata_decoder.h"
16 
17 #include <string>
18 
19 #include "draco/core/varint_decoding.h"
20 
21 namespace draco {
22 
MetadataDecoder()23 MetadataDecoder::MetadataDecoder() : buffer_(nullptr) {}
24 
DecodeMetadata(DecoderBuffer * in_buffer,Metadata * metadata)25 bool MetadataDecoder::DecodeMetadata(DecoderBuffer *in_buffer,
26                                      Metadata *metadata) {
27   if (!metadata) {
28     return false;
29   }
30   buffer_ = in_buffer;
31   return DecodeMetadata(metadata);
32 }
33 
DecodeGeometryMetadata(DecoderBuffer * in_buffer,GeometryMetadata * metadata)34 bool MetadataDecoder::DecodeGeometryMetadata(DecoderBuffer *in_buffer,
35                                              GeometryMetadata *metadata) {
36   if (!metadata) {
37     return false;
38   }
39   buffer_ = in_buffer;
40   uint32_t num_att_metadata = 0;
41   if (!DecodeVarint(&num_att_metadata, buffer_)) {
42     return false;
43   }
44   // Decode attribute metadata.
45   for (uint32_t i = 0; i < num_att_metadata; ++i) {
46     uint32_t att_unique_id;
47     if (!DecodeVarint(&att_unique_id, buffer_)) {
48       return false;
49     }
50     std::unique_ptr<AttributeMetadata> att_metadata =
51         std::unique_ptr<AttributeMetadata>(new AttributeMetadata());
52     att_metadata->set_att_unique_id(att_unique_id);
53     if (!DecodeMetadata(static_cast<Metadata *>(att_metadata.get()))) {
54       return false;
55     }
56     metadata->AddAttributeMetadata(std::move(att_metadata));
57   }
58   return DecodeMetadata(static_cast<Metadata *>(metadata));
59 }
60 
DecodeMetadata(Metadata * metadata)61 bool MetadataDecoder::DecodeMetadata(Metadata *metadata) {
62   struct MetadataPair {
63     Metadata *parent_metadata;
64     Metadata *decoded_metadata;
65   };
66   std::vector<MetadataPair> metadata_stack;
67   metadata_stack.push_back({nullptr, metadata});
68   while (!metadata_stack.empty()) {
69     const MetadataPair mp = metadata_stack.back();
70     metadata_stack.pop_back();
71     metadata = mp.decoded_metadata;
72 
73     if (mp.parent_metadata != nullptr) {
74       std::string sub_metadata_name;
75       if (!DecodeName(&sub_metadata_name)) {
76         return false;
77       }
78       std::unique_ptr<Metadata> sub_metadata =
79           std::unique_ptr<Metadata>(new Metadata());
80       metadata = sub_metadata.get();
81       if (!mp.parent_metadata->AddSubMetadata(sub_metadata_name,
82                                               std::move(sub_metadata))) {
83         return false;
84       }
85     }
86     if (metadata == nullptr) {
87       return false;
88     }
89 
90     uint32_t num_entries = 0;
91     if (!DecodeVarint(&num_entries, buffer_)) {
92       return false;
93     }
94     for (uint32_t i = 0; i < num_entries; ++i) {
95       if (!DecodeEntry(metadata)) {
96         return false;
97       }
98     }
99     uint32_t num_sub_metadata = 0;
100     if (!DecodeVarint(&num_sub_metadata, buffer_)) {
101       return false;
102     }
103     if (num_sub_metadata > buffer_->remaining_size()) {
104       // The decoded number of metadata items is unreasonably high.
105       return false;
106     }
107     for (uint32_t i = 0; i < num_sub_metadata; ++i) {
108       metadata_stack.push_back({metadata, nullptr});
109     }
110   }
111   return true;
112 }
113 
DecodeEntry(Metadata * metadata)114 bool MetadataDecoder::DecodeEntry(Metadata *metadata) {
115   std::string entry_name;
116   if (!DecodeName(&entry_name)) {
117     return false;
118   }
119   uint32_t data_size = 0;
120   if (!DecodeVarint(&data_size, buffer_)) {
121     return false;
122   }
123   if (data_size == 0) {
124     return false;
125   }
126   std::vector<uint8_t> entry_value(data_size);
127   if (!buffer_->Decode(&entry_value[0], data_size)) {
128     return false;
129   }
130   metadata->AddEntryBinary(entry_name, entry_value);
131   return true;
132 }
133 
DecodeName(std::string * name)134 bool MetadataDecoder::DecodeName(std::string *name) {
135   uint8_t name_len = 0;
136   if (!buffer_->Decode(&name_len)) {
137     return false;
138   }
139   name->resize(name_len);
140   if (name_len == 0) {
141     return true;
142   }
143   if (!buffer_->Decode(&name->at(0), name_len)) {
144     return false;
145   }
146   return true;
147 }
148 }  // namespace draco
149