diff --git a/src/struct_pack/examples/serialize/CMakeLists.txt b/src/struct_pack/examples/serialize/CMakeLists.txt index 1f35551c0..c87ed868b 100644 --- a/src/struct_pack/examples/serialize/CMakeLists.txt +++ b/src/struct_pack/examples/serialize/CMakeLists.txt @@ -1 +1,3 @@ -add_executable(serialize_example serialize.cpp) \ No newline at end of file +add_executable(serialize_example serialize.cpp) +add_executable(cross_language_demo simple_serialize.cpp) +add_executable(read_from_other deserialize_from_other_language.cpp) \ No newline at end of file diff --git a/src/struct_pack/examples/serialize/deserialize_from_other_language.cpp b/src/struct_pack/examples/serialize/deserialize_from_other_language.cpp new file mode 100644 index 000000000..cbf354c03 --- /dev/null +++ b/src/struct_pack/examples/serialize/deserialize_from_other_language.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include +#include + +#include "struct_pack/struct_pack.hpp" +#include "struct_pack/struct_pack/struct_pack_impl.hpp" + +struct person { + int age; + std::string name; +}; + +int main() +{ + std::fstream file; + file.open("./golang_serialize.txt", std::ios::in | std::ios::binary); + std::string buffer; + file >> buffer; + file.close(); + + person p{.age = 21, .name = "Betty"}; + person p2; + [[maybe_unused]] auto ec = struct_pack::deserialize_to(p2, buffer); + assert(ec == struct_pack::errc{}); + assert(p == p2); + + std::cout << p2.age << std::endl; + std::cout << p2.name << std::endl; + + + return 0; +} \ No newline at end of file diff --git a/src/struct_pack/examples/serialize/go_deserialize.go b/src/struct_pack/examples/serialize/go_deserialize.go new file mode 100644 index 000000000..f77d46e1d --- /dev/null +++ b/src/struct_pack/examples/serialize/go_deserialize.go @@ -0,0 +1,80 @@ +package main + +import ( + "fmt" + "io/ioutil" + "encoding/binary" +) + +type Person struct { + age uint32 + name string +} + +func deserialize_person(src []byte) (*Person) { + var person Person + hash_code := binary.LittleEndian.Uint32(src[0:4]) + if hash_code != 2242444774 { + return nil + } + + person.age = binary.LittleEndian.Uint32(src[4:]) // when computer is big-end there will be error + name_size := src[8] + person.name = string(src[9: 9 + name_size]) + return &person +} + +// In general, computer is little-endian +func serialize_person(person Person) (out []byte) { + var serialize_bytes []byte + var hash_code uint32 + hash_code = 2242444774 + hash_bytes := make([]byte, 4) // hashcode 4 bytes + age_u32_bytes := make([]byte, 4) // uint32 4 bytes + var str_size byte // str size 1 byte + // hash code to bytes + binary.LittleEndian.PutUint32(hash_bytes, hash_code) + serialize_bytes = append(serialize_bytes, hash_bytes[:]...) + // field age to bytes + binary.LittleEndian.PutUint32(age_u32_bytes, person.age) + serialize_bytes = append(serialize_bytes, age_u32_bytes[:]...) + // string size to bytes + str_size = (byte)(len(person.name)) + serialize_bytes = append(serialize_bytes, str_size) + // field name to bytes + serialize_bytes = append(serialize_bytes, ([]byte)(person.name)[:]...) + + return serialize_bytes +} + + +func main() { + fileName := "../../../../build/examples/example.txt" + data, err := ioutil.ReadFile(fileName); + if err != nil { + fmt.Println("Read file err, err = ", err) + return + } + // 1. deserialize from example.txt + de_person := deserialize_person(data) + + + fmt.Println("person age is: ", de_person.age) + fmt.Println("person name is: ", de_person.name) + // 2. serialize person to bytes + serialize_bytes := serialize_person(*de_person) + + fmt.Println(serialize_bytes) + // 3. deserialize from serialized bytes + de_person2 := deserialize_person(serialize_bytes) + fmt.Println("person age is: ", de_person2.age) + fmt.Println("person name is: ", de_person2.name) + + // 4. write serialized bytes to file + WritefileName := "../../../../build/examples/golang_serialize.txt" + err = ioutil.WriteFile(WritefileName, serialize_bytes, 0777) + if err != nil { + fmt.Println(err) + } + +} diff --git a/src/struct_pack/examples/serialize/simple_serialize.cpp b/src/struct_pack/examples/serialize/simple_serialize.cpp new file mode 100644 index 000000000..321e064a4 --- /dev/null +++ b/src/struct_pack/examples/serialize/simple_serialize.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022, Alibaba Group Holding Limited; + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "struct_pack/struct_pack.hpp" +#include "struct_pack/struct_pack/struct_pack_impl.hpp" + +static uint32_t deserialize_to_u32(const uint8_t bytes[4]) +{ + return ((bytes[3] << 24) + (bytes[2] << 16) + (bytes[1] << 8) + bytes[0]); + +} + + +static uint64_t deserialize_to_u64(const uint8_t m[8]) +{ + return ((uint64_t)m[7] << 56) | ((uint64_t)m[6] << 48) | ((uint64_t)m[5] << 40) | ((uint64_t)m[4] << 32) + | ((uint64_t)m[3] << 24) | ((uint64_t)m[2] << 16) | ((uint64_t)m[1] << 8) | ((uint64_t)m[0] << 0); +} + +struct person { + int age; + std::string name; +}; + +int main() +{ + person p{.age = 21, .name = "Betty"}; + std::string buffer = struct_pack::serialize(p); + + std::cout << typeid(buffer).name() << std::endl; + for (int i = 0; i < buffer.size(); i++) + std::cout << buffer[i] << std::endl; + + std::fstream file; + file.open("./example.txt", std::ios::out | std::ios::binary); + + file << buffer; + + file.close(); + + // c deserialize + // read serialize string and print deserialize's value + uint8_t *text = (uint8_t*)malloc(128); + FILE *fp = NULL; + fp = fopen("./example.txt", "r"); + fgets((char*)text, 128, fp); + fclose(fp); + // test hash code + uint32_t hash_code = deserialize_to_u32(text); + std::cout << "hash code is: " << hash_code << std::endl; + + int offset = 4; // first 4 bytes are hash code, no use for other language + int age = deserialize_to_u32(text + offset); + std::cout << "deserialize get age field: " << age << std::endl; + offset += 4; + // only one byte, maxsize string size is 255 + uint8_t string_length = text[offset]; + offset += 1; + char *name = (char*)malloc(string_length); + memcpy(name, (char*)(text + offset), string_length); + std::cout << "deserialize get name field: " << name << std::endl; + + free(text); + free(name); + + return 0; +}