You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@fury.apache.org by ch...@apache.org on 2024/09/02 11:24:50 UTC
(fury-site) branch main updated: docs: translate docs (#178)
This is an automated email from the ASF dual-hosted git repository.
chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fury-site.git
The following commit(s) were added to refs/heads/main by this push:
new 92c3d8f2 docs: translate docs (#178)
92c3d8f2 is described below
commit 92c3d8f2d9560ad04e1b3bf13f9f834a91eda7de
Author: shown <yu...@gmail.com>
AuthorDate: Mon Sep 2 19:24:46 2024 +0800
docs: translate docs (#178)
Signed-off-by: yuluo-yx <yu...@gmail.com>
Co-authored-by: Shawn Yang <ch...@apache.org>
---
.../current/guide/xlang_serialization_guide.md | 597 +++++++++++++++++++++
1 file changed, 597 insertions(+)
diff --git a/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/xlang_serialization_guide.md b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/xlang_serialization_guide.md
new file mode 100644
index 00000000..dce38676
--- /dev/null
+++ b/i18n/zh-CN/docusaurus-plugin-content-docs/current/guide/xlang_serialization_guide.md
@@ -0,0 +1,597 @@
+---
+title: 多语言序列化指南
+sidebar_position: 2
+id: xlang_object_graph_guide
+---
+
+## 跨语言对象图序列化
+
+### 序列化内置类型
+
+Apache Fury可以自动序列化编程语言的常见数据类型:primitive numeric types, string, binary, array, list, map 等。
+
+**Java**
+
+```java
+import org.apache.fury.*;
+import org.apache.fury.config.*;
+
+import java.util.*;
+
+public class Example1 {
+ public static void main(String[] args) {
+ Fury fury = Fury.builder().withLanguage(Language.XLANG).build();
+ List<Object> list = ofArrayList(true, false, "str", -1.1, 1, new int[100], new double[20]);
+ byte[] bytes = fury.serialize(list);
+ // bytes can be data serialized by other languages.
+ fury.deserialize(bytes);
+ Map<Object, Object> map = new HashMap<>();
+ map.put("k1", "v1");
+ map.put("k2", list);
+ map.put("k3", -1);
+ bytes = fury.serialize(map);
+ // bytes can be data serialized by other languages.
+ fury.deserialize(bytes);
+ }
+}
+```
+
+**Python**
+
+```python
+import pyfury
+import numpy as np
+
+fury = pyfury.Fury()
+object_list = [True, False, "str", -1.1, 1,
+ np.full(100, 0, dtype=np.int32), np.full(20, 0.0, dtype=np.double)]
+data = fury.serialize(object_list)
+# bytes can be data serialized by other languages.
+new_list = fury.deserialize(data)
+object_map = {"k1": "v1", "k2": object_list, "k3": -1}
+data = fury.serialize(object_map)
+# bytes can be data serialized by other languages.
+new_map = fury.deserialize(data)
+print(new_map)
+```
+
+**Golang**
+
+```go
+package main
+
+import furygo "github.com/apache/fury/fury/go/fury"
+import "fmt"
+
+func main() {
+ list := []interface{}{true, false, "str", -1.1, 1, make([]int32, 10), make([]float64, 20)}
+ fury := furygo.NewFury()
+ bytes, err := fury.Marshal(list)
+ if err != nil {
+ panic(err)
+ }
+ var newValue interface{}
+ // bytes can be data serialized by other languages.
+ if err := fury.Unmarshal(bytes, &newValue); err != nil {
+ panic(err)
+ }
+ fmt.Println(newValue)
+ dict := map[string]interface{}{
+ "k1": "v1",
+ "k2": list,
+ "k3": -1,
+ }
+ bytes, err = fury.Marshal(dict)
+ if err != nil {
+ panic(err)
+ }
+ // bytes can be data serialized by other languages.
+ if err := fury.Unmarshal(bytes, &newValue); err != nil {
+ panic(err)
+ }
+ fmt.Println(newValue)
+}
+```
+
+**JavaScript**
+
+```javascript
+import Fury from '@furyjs/fury';
+
+/**
+ * @furyjs/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above.
+ * Experimental feature, installation success cannot be guaranteed at this moment
+ * If you are unable to install the module, replace it with `const hps = null;`
+ **/
+import hps from '@furyjs/hps';
+
+const fury = new Fury({ hps });
+const input = fury.serialize('hello fury');
+const result = fury.deserialize(input);
+console.log(result);
+```
+
+**Rust**
+
+```rust
+use chrono::{NaiveDate, NaiveDateTime};
+use fury::{from_buffer, to_buffer, Fury};
+use std::collections::HashMap;
+
+fn run() {
+ let bin: Vec<u8> = to_buffer(&"hello".to_string());
+ let obj: String = from_buffer(&bin).expect("should success");
+ assert_eq!("hello".to_string(), obj);
+}
+```
+
+### 序列化自定义类型
+
+序列化用户定义的类型需要使用注册 API 注册自定义类型,以便在不同语言中建立类型之间的映射关系。
+
+**Java**
+
+```java
+import org.apache.fury.*;
+import org.apache.fury.config.*;
+import java.util.*;
+
+public class Example2 {
+ public static class SomeClass1 {
+ Object f1;
+ Map<Byte, Integer> f2;
+ }
+
+ public static class SomeClass2 {
+ Object f1;
+ String f2;
+ List<Object> f3;
+ Map<Byte, Integer> f4;
+ Byte f5;
+ Short f6;
+ Integer f7;
+ Long f8;
+ Float f9;
+ Double f10;
+ short[] f11;
+ List<Short> f12;
+ }
+
+ public static Object createObject() {
+ SomeClass1 obj1 = new SomeClass1();
+ obj1.f1 = true;
+ obj1.f2 = ofHashMap((byte) -1, 2);
+ SomeClass2 obj = new SomeClass2();
+ obj.f1 = obj1;
+ obj.f2 = "abc";
+ obj.f3 = ofArrayList("abc", "abc");
+ obj.f4 = ofHashMap((byte) 1, 2);
+ obj.f5 = Byte.MAX_VALUE;
+ obj.f6 = Short.MAX_VALUE;
+ obj.f7 = Integer.MAX_VALUE;
+ obj.f8 = Long.MAX_VALUE;
+ obj.f9 = 1.0f / 2;
+ obj.f10 = 1 / 3.0;
+ obj.f11 = new short[]{(short) 1, (short) 2};
+ obj.f12 = ofArrayList((short) -1, (short) 4);
+ return obj;
+ }
+
+ // mvn exec:java -Dexec.mainClass="org.apache.fury.examples.Example2"
+ public static void main(String[] args) {
+ Fury fury = Fury.builder().withLanguage(Language.XLANG).build();
+ fury.register(SomeClass1.class, "example.SomeClass1");
+ fury.register(SomeClass2.class, "example.SomeClass2");
+ byte[] bytes = fury.serialize(createObject());
+ // bytes can be data serialized by other languages.
+ System.out.println(fury.deserialize(bytes));
+ }
+}
+```
+
+**Python**
+
+```python
+from dataclasses import dataclass
+from typing import List, Dict, Any
+import pyfury, array
+
+
+@dataclass
+class SomeClass1:
+ f1: Any
+ f2: Dict[pyfury.Int8Type, pyfury.Int32Type]
+
+
+@dataclass
+class SomeClass2:
+ f1: Any = None
+ f2: str = None
+ f3: List[str] = None
+ f4: Dict[pyfury.Int8Type, pyfury.Int32Type] = None
+ f5: pyfury.Int8Type = None
+ f6: pyfury.Int16Type = None
+ f7: pyfury.Int32Type = None
+ # int type will be taken as `pyfury.Int64Type`.
+ # use `pyfury.Int32Type` for type hint if peer
+ # are more narrow type.
+ f8: int = None
+ f9: pyfury.Float32Type = None
+ # float type will be taken as `pyfury.Float64Type`
+ f10: float = None
+ f11: pyfury.Int16ArrayType = None
+ f12: List[pyfury.Int16Type] = None
+
+
+if __name__ == "__main__":
+ f = pyfury.Fury()
+ f.register_class(SomeClass1, type_tag="example.SomeClass1")
+ f.register_class(SomeClass2, type_tag="example.SomeClass2")
+ obj1 = SomeClass1(f1=True, f2={-1: 2})
+ obj = SomeClass2(
+ f1=obj1,
+ f2="abc",
+ f3=["abc", "abc"],
+ f4={1: 2},
+ f5=2 ** 7 - 1,
+ f6=2 ** 15 - 1,
+ f7=2 ** 31 - 1,
+ f8=2 ** 63 - 1,
+ f9=1.0 / 2,
+ f10=1 / 3.0,
+ f11=array.array("h", [1, 2]),
+ f12=[-1, 4],
+ )
+ data = f.serialize(obj)
+ # bytes can be data serialized by other languages.
+ print(f.deserialize(data))
+```
+
+**Golang**
+
+```go
+package main
+
+import furygo "github.com/apache/fury/fury/go/fury"
+import "fmt"
+
+func main() {
+ type SomeClass1 struct {
+ F1 interface{}
+ F2 string
+ F3 []interface{}
+ F4 map[int8]int32
+ F5 int8
+ F6 int16
+ F7 int32
+ F8 int64
+ F9 float32
+ F10 float64
+ F11 []int16
+ F12 fury.Int16Slice
+ }
+
+ type SomeClas2 struct {
+ F1 interface{}
+ F2 map[int8]int32
+ }
+ fury := furygo.NewFury()
+ if err := fury.RegisterTagType("example.SomeClass1", SomeClass1{}); err != nil {
+ panic(err)
+ }
+ if err := fury.RegisterTagType("example.SomeClass2", SomeClass2{}); err != nil {
+ panic(err)
+ }
+ obj1 := &SomeClass1{}
+ obj1.F1 = true
+ obj1.F2 = map[int8]int32{-1: 2}
+ obj := &SomeClass1{}
+ obj.F1 = obj1
+ obj.F2 = "abc"
+ obj.F3 = []interface{}{"abc", "abc"}
+ f4 := map[int8]int32{1: 2}
+ obj.F4 = f4
+ obj.F5 = fury.MaxInt8
+ obj.F6 = fury.MaxInt16
+ obj.F7 = fury.MaxInt32
+ obj.F8 = fury.MaxInt64
+ obj.F9 = 1.0 / 2
+ obj.F10 = 1 / 3.0
+ obj.F11 = []int16{1, 2}
+ obj.F12 = []int16{-1, 4}
+ bytes, err := fury.Marshal(obj);
+ if err != nil {
+ panic(err)
+ }
+ var newValue interface{}
+ // bytes can be data serialized by other languages.
+ if err := fury.Unmarshal(bytes, &newValue); err != nil {
+ panic(err)
+ }
+ fmt.Println(newValue)
+}
+```
+
+**JavaScript**
+
+```javascript
+import Fury, { Type, InternalSerializerType } from '@furyjs/fury';
+
+/**
+ * @furyjs/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above.
+ * Experimental feature, installation success cannot be guaranteed at this moment
+ * If you are unable to install the module, replace it with `const hps = null;`
+ **/
+import hps from '@furyjs/hps';
+
+// Now we describe data structures using JSON, but in the future, we will use more ways.
+const description = Type.object('example.foo', {
+ foo: Type.string(),
+});
+const fury = new Fury({ hps });
+const { serialize, deserialize } = fury.registerSerializer(description);
+const input = serialize({ foo: 'hello fury' });
+const result = deserialize(input);
+console.log(result);
+```
+
+**Rust**
+
+```rust
+use chrono::{NaiveDate, NaiveDateTime};
+use fury::{from_buffer, to_buffer, Fury};
+use std::collections::HashMap;
+
+#[test]
+fn complex_struct() {
+ #[derive(Fury, Debug, PartialEq)]
+ #[tag("example.foo2")]
+ struct Animal {
+ category: String,
+ }
+
+ #[derive(Fury, Debug, PartialEq)]
+ #[tag("example.foo")]
+ struct Person {
+ c1: Vec<u8>, // binary
+ c2: Vec<i16>, // primitive array
+ animal: Vec<Animal>,
+ c3: Vec<Vec<u8>>,
+ name: String,
+ c4: HashMap<String, String>,
+ age: u16,
+ op: Option<String>,
+ op2: Option<String>,
+ date: NaiveDate,
+ time: NaiveDateTime,
+ c5: f32,
+ c6: f64,
+ }
+ let person: Person = Person {
+ c1: vec![1, 2, 3],
+ c2: vec![5, 6, 7],
+ c3: vec![vec![1, 2], vec![1, 3]],
+ animal: vec![Animal {
+ category: "Dog".to_string(),
+ }],
+ c4: HashMap::from([
+ ("hello1".to_string(), "hello2".to_string()),
+ ("hello2".to_string(), "hello3".to_string()),
+ ]),
+ age: 12,
+ name: "helo".to_string(),
+ op: Some("option".to_string()),
+ op2: None,
+ date: NaiveDate::from_ymd_opt(2025, 12, 12).unwrap(),
+ time: NaiveDateTime::from_timestamp_opt(1689912359, 0).unwrap(),
+ c5: 2.0,
+ c6: 4.0,
+ };
+
+ let bin: Vec<u8> = to_buffer(&person);
+ let obj: Person = from_buffer(&bin).expect("should success");
+ assert_eq!(person, obj);
+}
+```
+
+### 序列化共享引用和循环引用
+
+共享引用和循环引用可自动序列化,不会出现重复数据或递归错误。
+
+**Java**
+
+```java
+import org.apache.fury.*;
+import org.apache.fury.config.*;
+import java.util.*;
+
+public class ReferenceExample {
+ public static class SomeClass {
+ SomeClass f1;
+ Map<String, String> f2;
+ Map<String, String> f3;
+ }
+
+ public static Object createObject() {
+ SomeClass obj = new SomeClass();
+ obj.f1 = obj;
+ obj.f2 = ofHashMap("k1", "v1", "k2", "v2");
+ obj.f3 = obj.f2;
+ return obj;
+ }
+
+ // mvn exec:java -Dexec.mainClass="org.apache.fury.examples.ReferenceExample"
+ public static void main(String[] args) {
+ Fury fury = Fury.builder().withLanguage(Language.XLANG)
+ .withRefTracking(true).build();
+ fury.register(SomeClass.class, "example.SomeClass");
+ byte[] bytes = fury.serialize(createObject());
+ // bytes can be data serialized by other languages.
+ System.out.println(fury.deserialize(bytes));
+ }
+}
+```
+
+**Python**
+
+```python
+from typing import Dict
+import pyfury
+
+class SomeClass:
+ f1: "SomeClass"
+ f2: Dict[str, str]
+ f3: Dict[str, str]
+
+fury = pyfury.Fury(ref_tracking=True)
+fury.register_class(SomeClass, type_tag="example.SomeClass")
+obj = SomeClass()
+obj.f2 = {"k1": "v1", "k2": "v2"}
+obj.f1, obj.f3 = obj, obj.f2
+data = fury.serialize(obj)
+# bytes can be data serialized by other languages.
+print(fury.deserialize(data))
+```
+
+**Golang**
+
+```go
+package main
+
+import furygo "github.com/apache/fury/fury/go/fury"
+import "fmt"
+
+func main() {
+ type SomeClass struct {
+ F1 *SomeClass
+ F2 map[string]string
+ F3 map[string]string
+ }
+ fury := furygo.NewFury(true)
+ if err := fury.RegisterTagType("example.SomeClass", SomeClass{}); err != nil {
+ panic(err)
+ }
+ value := &SomeClass{F2: map[string]string{"k1": "v1", "k2": "v2"}}
+ value.F3 = value.F2
+ value.F1 = value
+ bytes, err := fury.Marshal(value)
+ if err != nil {
+ }
+ var newValue interface{}
+ // bytes can be data serialized by other languages.
+ if err := fury.Unmarshal(bytes, &newValue); err != nil {
+ panic(err)
+ }
+ fmt.Println(newValue)
+}
+```
+
+**JavaScript**
+
+```javascript
+import Fury, { Type } from '@furyjs/fury';
+/**
+ * @furyjs/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above.
+ * Experimental feature, installation success cannot be guaranteed at this moment
+ * If you are unable to install the module, replace it with `const hps = null;`
+ **/
+import hps from '@furyjs/hps';
+
+const description = Type.object('example.foo', {
+ foo: Type.string(),
+ bar: Type.object('example.foo'),
+});
+
+const fury = new Fury({ hps });
+const { serialize, deserialize } = fury.registerSerializer(description);
+const data: any = {
+ foo: 'hello fury',
+};
+data.bar = data;
+const input = serialize(data);
+const result = deserialize(input);
+console.log(result.bar.foo === result.foo);
+```
+
+**JavaScript**
+Reference cannot be implemented because of rust ownership restrictions
+
+### Zero-Copy Serialization
+
+**Java**
+
+```java
+import org.apache.fury.*;
+import org.apache.fury.config.*;
+import org.apache.fury.serializers.BufferObject;
+import org.apache.fury.memory.MemoryBuffer;
+
+import java.util.*;
+import java.util.stream.Collectors;
+
+public class ZeroCopyExample {
+ // mvn exec:java -Dexec.mainClass="io.ray.fury.examples.ZeroCopyExample"
+ public static void main(String[] args) {
+ Fury fury = Fury.builder().withLanguage(Language.XLANG).build();
+ List<Object> list = ofArrayList("str", new byte[1000], new int[100], new double[100]);
+ Collection<BufferObject> bufferObjects = new ArrayList<>();
+ byte[] bytes = fury.serialize(list, e -> !bufferObjects.add(e));
+ // bytes can be data serialized by other languages.
+ List<MemoryBuffer> buffers = bufferObjects.stream()
+ .map(BufferObject::toBuffer).collect(Collectors.toList());
+ System.out.println(fury.deserialize(bytes, buffers));
+ }
+}
+```
+
+**Python**
+
+```python
+import array
+import pyfury
+import numpy as np
+
+fury = pyfury.Fury()
+list_ = ["str", bytes(bytearray(1000)),
+ array.array("i", range(100)), np.full(100, 0.0, dtype=np.double)]
+serialized_objects = []
+data = fury.serialize(list_, buffer_callback=serialized_objects.append)
+buffers = [o.to_buffer() for o in serialized_objects]
+# bytes can be data serialized by other languages.
+print(fury.deserialize(data, buffers=buffers))
+```
+
+**Golang**
+
+```go
+package main
+
+import furygo "github.com/apache/fury/fury/go/fury"
+import "fmt"
+
+func main() {
+ fury := furygo.NewFury()
+ list := []interface{}{"str", make([]byte, 1000)}
+ buf := fury.NewByteBuffer(nil)
+ var bufferObjects []fury.BufferObject
+ fury.Serialize(buf, list, func(o fury.BufferObject) bool {
+ bufferObjects = append(bufferObjects, o)
+ return false
+ })
+ var newList []interface{}
+ var buffers []*fury.ByteBuffer
+ for _, o := range bufferObjects {
+ buffers = append(buffers, o.ToBuffer())
+ }
+ if err := fury.Deserialize(buf, &newList, buffers); err != nil {
+ panic(err)
+ }
+ fmt.Println(newList)
+}
+```
+
+**JavaScript**
+
+```javascript
+// Coming soon
+```
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@fury.apache.org
For additional commands, e-mail: commits-help@fury.apache.org