Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cross language demo]go language deserialize demo #128

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/struct_pack/examples/serialize/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
add_executable(serialize_example serialize.cpp)
add_executable(serialize_example serialize.cpp)
add_executable(cross_language_demo simple_serialize.cpp)
add_executable(read_from_other deserialize_from_other_language.cpp)
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>
#include <memory>

#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;
}
80 changes: 80 additions & 0 deletions src/struct_pack/examples/serialize/go_deserialize.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package main
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add ci for this demo is better

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok,I will change package name and add test for this demo


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)
}

}
87 changes: 87 additions & 0 deletions src/struct_pack/examples/serialize/simple_serialize.cpp
Original file line number Diff line number Diff line change
@@ -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 <cassert>
#include <cstdint>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <string>
#include <memory>

#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<std::string>(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;
}