1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
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 
16 #include "rdb_cloud_data_translate.h"
17 
18 #include "utils/endian_converter.h"
19 #include "value_proxy.h"
20 
21 namespace OHOS::DistributedRdb {
22 using Asset = DistributedDB::Asset;
23 using Assets = DistributedDB::Assets;
24 using DataAsset = NativeRdb::ValueObject::Asset;
25 using DataAssets = NativeRdb::ValueObject::Assets;
26 using  ValueProxy = DistributedData::ValueProxy;
AssetToBlob(const Asset & asset)27 std::vector<uint8_t> RdbCloudDataTranslate::AssetToBlob(const Asset &asset)
28 {
29     std::vector<uint8_t> rawData;
30     Asset dbAsset = asset;
31     dbAsset.flag = static_cast<uint32_t>(DistributedDB::AssetOpType::NO_CHANGE);
32     DataAsset dataAsset = ValueProxy::TempAsset(std::move(dbAsset));
33     InnerAsset innerAsset(dataAsset);
34     auto data = Serializable::Marshall(innerAsset);
35     auto size = DistributedData::HostToNet((uint16_t)data.length());
36     auto leMagic = DistributedData::HostToNet(ASSET_MAGIC);
37     auto magicU8 = reinterpret_cast<uint8_t *>(const_cast<uint32_t *>(&leMagic));
38     rawData.insert(rawData.end(), magicU8, magicU8 + sizeof(ASSET_MAGIC));
39     rawData.insert(rawData.end(), reinterpret_cast<uint8_t *>(&size),
40         reinterpret_cast<uint8_t *>(&size) + sizeof(size));
41     rawData.insert(rawData.end(), data.begin(), data.end());
42     return rawData;
43 }
44 
AssetsToBlob(const Assets & assets)45 std::vector<uint8_t> RdbCloudDataTranslate::AssetsToBlob(const Assets &assets)
46 {
47     std::vector<uint8_t> rawData;
48     auto num = DistributedData::HostToNet((uint16_t)assets.size());
49     auto leMagic = DistributedData::HostToNet(ASSETS_MAGIC);
50     auto magicU8 = reinterpret_cast<uint8_t *>(const_cast<uint32_t *>(&leMagic));
51     rawData.insert(rawData.end(), magicU8, magicU8 + sizeof(ASSETS_MAGIC));
52     rawData.insert(rawData.end(), reinterpret_cast<uint8_t *>(&num), reinterpret_cast<uint8_t *>(&num) + sizeof(num));
53     for (auto &asset : assets) {
54         auto data = AssetToBlob(asset);
55         rawData.insert(rawData.end(), data.begin(), data.end());
56     }
57     return rawData;
58 }
59 
BlobToAsset(const std::vector<uint8_t> & blob)60 Asset RdbCloudDataTranslate::BlobToAsset(const std::vector<uint8_t> &blob)
61 {
62     DataAsset asset;
63     if (ParserRawData(blob.data(), blob.size(), asset) == 0) {
64         return {};
65     }
66     return ValueProxy::Convert(asset);
67 }
68 
BlobToAssets(const std::vector<uint8_t> & blob)69 Assets RdbCloudDataTranslate::BlobToAssets(const std::vector<uint8_t> &blob)
70 {
71     DataAssets assets;
72     if (ParserRawData(blob.data(), blob.size(), assets) == 0) {
73         return {};
74     }
75     return ValueProxy::Convert(assets);
76 }
77 
ParserRawData(const uint8_t * data,size_t length,DataAsset & asset)78 size_t RdbCloudDataTranslate::ParserRawData(const uint8_t *data, size_t length, DataAsset &asset)
79 {
80     size_t used = 0;
81     uint16_t size = 0;
82 
83     if (sizeof(ASSET_MAGIC) > length - used) {
84         return 0;
85     }
86     std::vector<uint8_t> alignData;
87     alignData.assign(data, data + sizeof(ASSET_MAGIC));
88     used += sizeof(ASSET_MAGIC);
89     auto hostMagicWord = DistributedData::NetToHost(*(reinterpret_cast<decltype(&ASSET_MAGIC)>(alignData.data())));
90     if (hostMagicWord != ASSET_MAGIC) {
91         return 0;
92     }
93     if (sizeof(size) > length - used) {
94         return 0;
95     }
96     alignData.assign(data + used, data + used + sizeof(size));
97     used += sizeof(size);
98     size = DistributedData::NetToHost(*(reinterpret_cast<decltype(&size)>(alignData.data())));
99     if (size > length - used) {
100         return 0;
101     }
102     auto rawData = std::string(reinterpret_cast<const char *>(&data[used]), size);
103     InnerAsset innerAsset(asset);
104     if (!innerAsset.Unmarshall(rawData)) {
105         return 0;
106     }
107     used += size;
108     return used;
109 }
110 
ParserRawData(const uint8_t * data,size_t length,DataAssets & assets)111 size_t RdbCloudDataTranslate::ParserRawData(const uint8_t *data, size_t length, DataAssets &assets)
112 {
113     size_t used = 0;
114     uint16_t num = 0;
115 
116     if (sizeof(ASSETS_MAGIC) > length - used) {
117         return 0;
118     }
119     std::vector<uint8_t> alignData;
120     alignData.assign(data, data + sizeof(ASSETS_MAGIC));
121     used += sizeof(ASSETS_MAGIC);
122     auto hostMagicWord = DistributedData::NetToHost(*(reinterpret_cast<decltype(&ASSETS_MAGIC)>(alignData.data())));
123     if (hostMagicWord != ASSETS_MAGIC) {
124         return 0;
125     }
126 
127     if (sizeof(num) > length - used) {
128         return 0;
129     }
130     alignData.assign(data, data + sizeof(num));
131     num = DistributedData::NetToHost(*(reinterpret_cast<decltype(&num)>(alignData.data())));
132     used += sizeof(num);
133     uint16_t count = 0;
134     while (used < length && count < num) {
135         DataAsset asset;
136         auto dataLen = ParserRawData(&data[used], length - used, asset);
137         if (dataLen == 0) {
138             break;
139         }
140         used += dataLen;
141         assets.push_back(std::move(asset));
142         count++;
143     }
144     return used;
145 }
146 
Marshal(OHOS::DistributedData::Serializable::json & node) const147 bool RdbCloudDataTranslate::InnerAsset::Marshal(OHOS::DistributedData::Serializable::json &node) const
148 {
149     bool ret = true;
150     ret = SetValue(node[GET_NAME(version)], asset_.version) && ret;
151     ret = SetValue(node[GET_NAME(status)], asset_.status) && ret;
152     ret = SetValue(node[GET_NAME(expiresTime)], asset_.expiresTime) && ret;
153     ret = SetValue(node[GET_NAME(id)], asset_.id) && ret;
154     ret = SetValue(node[GET_NAME(name)], asset_.name) && ret;
155     ret = SetValue(node[GET_NAME(uri)], asset_.uri) && ret;
156     ret = SetValue(node[GET_NAME(path)], asset_.path) && ret;
157     ret = SetValue(node[GET_NAME(createTime)], asset_.createTime) && ret;
158     ret = SetValue(node[GET_NAME(modifyTime)], asset_.modifyTime) && ret;
159     ret = SetValue(node[GET_NAME(size)], asset_.size) && ret;
160     ret = SetValue(node[GET_NAME(hash)], asset_.hash) && ret;
161     return ret;
162 }
163 
Unmarshal(const OHOS::DistributedData::Serializable::json & node)164 bool RdbCloudDataTranslate::InnerAsset::Unmarshal(const OHOS::DistributedData::Serializable::json &node)
165 {
166     bool ret = true;
167     ret = GetValue(node, GET_NAME(version), asset_.version) && ret;
168     ret = GetValue(node, GET_NAME(status), asset_.status) && ret;
169     ret = GetValue(node, GET_NAME(expiresTime), asset_.expiresTime) && ret;
170     ret = GetValue(node, GET_NAME(id), asset_.id) && ret;
171     ret = GetValue(node, GET_NAME(name), asset_.name) && ret;
172     ret = GetValue(node, GET_NAME(uri), asset_.uri) && ret;
173     ret = GetValue(node, GET_NAME(path), asset_.path) && ret;
174     ret = GetValue(node, GET_NAME(createTime), asset_.createTime) && ret;
175     ret = GetValue(node, GET_NAME(modifyTime), asset_.modifyTime) && ret;
176     ret = GetValue(node, GET_NAME(size), asset_.size) && ret;
177     ret = GetValue(node, GET_NAME(hash), asset_.hash) && ret;
178     return ret;
179 }
180 } // namespace OHOS::DistributedRdb
181