Skip to content

Commit 6ae9d78

Browse files
author
auxten
committed
Update docs
1 parent 8f9444a commit 6ae9d78

File tree

5 files changed

+210
-232
lines changed

5 files changed

+210
-232
lines changed

README.md

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,55 @@
11
Hash Stable Pack
22
=======
3-
This is a code generation tool and serialization library for Calculation of Stable Hash for content. Basically it will generate an `MarshalHash` method which follow the MessagePack but **without the key**.
3+
This is a code generation tool for **QUICK** struct content compare or hash computation.
44

55
### For
6-
- Quick compare nested struct without reflection
7-
- Quick calculation of struct hash or signature without reflection
6+
- Quick compare nested struct without reflection (10~20 times faster)
7+
8+
```go
9+
BenchmarkCompare/benchmark_reflect-8 100000 20074 ns/op //reflect.DeepEqual
10+
BenchmarkCompare/benchmark_hsp-8 500000 2322 ns/op
11+
BenchmarkCompare/benchmark_hsp_1_cached-8 1000000 1101 ns/op
12+
BenchmarkCompare/benchmark_hsp_both_cached-8 100000000 11.2 ns/op
13+
```
14+
bench cases see [here](test/hashstable_test.go)
15+
16+
- Quick calculation of struct hash or signature without reflection. used in [CovenantSQL](https://github.com/CovenantSQL/CovenantSQL) for block hash.
17+
18+
### How
19+
20+
Basically it will generate an `MarshalHash` method which follow the [MessagePack Spec](https://github.com/msgpack/msgpack/blob/master/spec.md) but :
21+
22+
1. Without the struct key.
23+
1. Stable output of map.
24+
1. Can be used to compare different type with same hsp tag.
825

9-
### How?
1026

1127
That is the following 2 structs with different member name
12-
For more: see [Spec in Chinese](spec.md)
13-
```go
14-
package person
1528

29+
For more: see [test cases](test)
30+
```go
1631
//go:generate hsp
32+
1733
type Person1 struct {
18-
Name1 string
19-
Age1 int
20-
Address1 string
21-
unexported1 bool // this field is ignored
34+
Name string
35+
Age int
36+
Address string
37+
Map map[string]int
38+
unexported bool // this field is ignored
39+
Unexported string `hsp:"-"` // this field is ignored
2240
}
2341
24-
// Same struct with "string, string, int, bool"
2542
type Person2 struct {
26-
Name2 string
27-
Address2 string
28-
Age2 int
29-
unexported2 bool // this field is ignored
43+
Name string
44+
Address string
45+
Age int
46+
Map222 map[string]int `hspack:"Map"`
47+
unexported bool // this field is ignored
48+
Unexported string `hsp:"-"` // this field is ignored
3049
}
3150
```
3251

33-
But with the same type and content of exported member, `MarshalHash` will produce the same bytes array:
52+
But with the same name and content of exported member, `MarshalHash` will produce the same bytes array:
3453
```go
3554
package person
3655
@@ -41,16 +60,18 @@ import (
4160
4261
func TestMarshalHashAccountStable3(t *testing.T) {
4362
p1 := Person1{
44-
Name1: "Auxten",
45-
Age1: 28,
46-
Address1: "@CovenantSQL.io",
47-
unexported1: false,
63+
Name: "Auxten",
64+
Address: "@CovenantSQL.io",
65+
Age: 70,
66+
Map: map[string]int{"ss": 2, "s": 1, "sss": 3},
67+
unexported: false,
4868
}
4969
p2 := Person2{
50-
Name2: "Auxten",
51-
Address2: "@CovenantSQL.io",
52-
Age2: 28,
53-
unexported2: true,
70+
Name: "Auxten",
71+
Address: "@CovenantSQL.io",
72+
Age: 70,
73+
Map222: map[string]int{"ss": 2, "s": 1, "sss": 3},
74+
unexported: true,
5475
}
5576
bts1, err := p1.MarshalHash()
5677
if err != nil {
@@ -65,8 +86,7 @@ func TestMarshalHashAccountStable3(t *testing.T) {
6586
}
6687
}
6788
```
68-
the order of struct member is sorted by type name, so "string, int", "int, string" is equivalent.
69-
89+
the order of struct member is sorted by struct tag (if not, use name)
7090

7191

7292
You can read more about MessagePack [in the wiki](http://github.com/tinylib/msgp/wiki), or at [msgpack.org](http://msgpack.org).
@@ -75,14 +95,10 @@ You can read more about MessagePack [in the wiki](http://github.com/tinylib/msgp
7595

7696
- Use Go as your schema language
7797
- Performance
78-
- [JSON interop](http://godoc.org/github.com/tinylib/msgp/msgp#CopyToJSON)
79-
- [User-defined extensions](http://github.com/tinylib/msgp/wiki/Using-Extensions)
80-
- Type safety
81-
- Encoding flexibility
8298

8399
### Why not?
84100

85-
- MessagePack: member name is unnecessary, different implementation may add some fields which made result undetermined.
101+
- MessagePack: member name is unnecessary, different implementation may add some fields which made result undetermined. And also golang's map...
86102
- Prorobuf: struct must defined in proto language, and other limitations discussed [here](https://gist.github.com/kchristidis/39c8b310fd9da43d515c4394c3cd9510)
87103
88104
### Quickstart
@@ -122,22 +138,6 @@ func (z *Test) Msgsize() (s int)
122138
- Support for arbitrary type system extensions
123139
- File-based dependency model means fast codegen regardless of source tree size.
124140

125-
Consider the following:
126-
```go
127-
const Eight = 8
128-
type MyInt int
129-
type Data []byte
130-
131-
type Struct struct {
132-
Which map[string]*MyInt
133-
Other Data
134-
Nums [Eight]float64
135-
}
136-
```
137-
As long as the declarations of `MyInt` and `Data` are in the same file as `Struct`, the parser will determine that the type information for `MyInt` and `Data` can be passed into the definition of `Struct` before its methods are generated.
138-
139-
### Known issues
140-
- map type is not supported. will cause undetermined marshal content.
141141

142142
### License
143143

spec.md

Lines changed: 0 additions & 139 deletions
This file was deleted.

test/covenantsql.go

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type HeaderTest struct {
2525
Version int32 `hsp:"01"`
2626
TestName string `hsp:"00"`
2727
TestArray []byte
28+
S Struct
2829
Producer proto.NodeID `hsp:"02"`
2930
GenesisHash []hash.Hash `hsp:"06"`
3031
ParentHash []*hash.Hash `hsp:"03"`
@@ -35,9 +36,10 @@ type HeaderTest struct {
3536

3637
// HeaderTest is a block header.
3738
type HeaderTest2 struct {
39+
S Struct // position is not relevant
3840
Version2 int32 `hsp:"01"`
3941
TestName2 string `hsp:"00"`
40-
TestArray2 []byte
42+
TestArray []byte
4143
Producer2 proto.NodeID `hsp:"02"`
4244
GenesisHash2 []hash.Hash `hsp:"06"`
4345
ParentHash2 []*hash.Hash `hsp:"03"`
@@ -47,17 +49,19 @@ type HeaderTest2 struct {
4749
}
4850

4951
type Person1 struct {
50-
Name1 string
51-
Age1 int
52-
Address1 string
53-
Map map[string]int
54-
unexported1 bool // this field is ignored
52+
Name string
53+
Age int
54+
Address string
55+
Map map[string]int
56+
unexported bool // this field is ignored
57+
Unexported string `hsp:"-"` // this field is ignored
5558
}
5659

5760
type Person2 struct {
58-
Name2 string
59-
Address2 string
60-
Age2 int
61-
Map222 map[string]int `hspack:"Map"`
62-
unexported2 bool // this field is ignored
61+
Name string
62+
Address string
63+
Age int
64+
Map222 map[string]int `hspack:"Map"`
65+
unexported bool // this field is ignored
66+
Unexported string `hsp:"-"` // this field is ignored
6367
}

0 commit comments

Comments
 (0)