odps_protobuf 0.1.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 249cda7a33537c127906c055663c937e51cc735d
4
- data.tar.gz: 2617bfa261c6e2c25318ff940360cb1c277e7f70
3
+ metadata.gz: 465f2649c2d0446a126ea79c290507144791b1bf
4
+ data.tar.gz: 3cfabff435ea2d4414a40380331dbc9cc49e75e9
5
5
  SHA512:
6
- metadata.gz: f50cbfd6f4e20a980749ca7c70b29ba8a1963feabaae279266dc13458b60cf5e29438632cda2eaa8a4c1313381093de9aedc4742c05dc9011cda2e7ff5a37657
7
- data.tar.gz: 253af63a58045c5786cbd8009e2ca63b914b71ed3d4c75720046c919dff35c5b07c81e47e553c83e695744dd4a864fc2a2ebb5b29b602108d57e0fc06a549b2e
6
+ metadata.gz: a245fe543ad6ee026dbaf56e58c1e660a735d207ad90e5d70c654e8aa9833d075373e1e8e7d32dec04ec3b2d955b918a98c9402f1505d451dee62ed54c91faca
7
+ data.tar.gz: 8c8b077630b1fd5f96c4f21f81607311ae5fa2a851e7a81163b32fd50ae18e5dda40f3d66ac06731c1f8821bc8a40dee26fd2db5303e21d10d238b2da28298d6
data/README.md CHANGED
@@ -1,16 +1,12 @@
1
1
  # OdpsProtobuf
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/odps_protobuf`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ Protobuf for ODPS
6
4
 
7
5
  ## Installation
8
6
 
9
7
  Add this line to your application's Gemfile:
10
8
 
11
- ```ruby
12
- gem 'odps_protobuf'
13
- ```
9
+ gem 'odps_protobuf'
14
10
 
15
11
  And then execute:
16
12
 
@@ -22,11 +18,26 @@ Or install it yourself as:
22
18
 
23
19
  ## Usage
24
20
 
25
- serializer = Odps::ProtobufSerializer.new
26
- serializer.serialize(records, schema) # => serialized string
27
21
 
28
- deserializer = Odps::ProtobufDeSerializer.new
29
- deserializer.deserialize(serialized_string, schema) # => unserialized records
22
+ schema = {
23
+ 'columns' => [
24
+ { 'name' => 'uuid', 'type' => 'bigint' },
25
+ { 'name' => 'name', 'type' => 'string' },
26
+ { 'name' => 'price', 'type' => 'decimal' },
27
+ { 'name' => 'discount', 'type' => 'double' },
28
+ { 'name' => 'in_stock', 'type' => 'boolean' },
29
+ { 'name' => 'created_time', 'type' => 'datetime' }
30
+ ]
31
+ }
32
+ record1 = [1, 'apple', BigDecimal.new("1.2"), 0.5, true, Time.now]
33
+ record2 = [1000, 'red apple', BigDecimal.new("12.5"), 0.9, false, Time.now]
34
+
35
+ serializer = OdpsProtobuf::Serializer.new
36
+
37
+ protobufed_str = serializer.serialize([record1, record2], schema) # => "\b\u0002\u0012\u0005apple\u001A\u00031.2!\u0000\u0000\u0000\u0000\u0000\u0000\xE0?(\u00010\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007F\xCCӥ\xE2\u000F\b\xD0\u000F\u0012\tred apple\u001A\u000412.5!\xCD\xCC\xCC\xCC\xCC\xCC\xEC?(\u00000\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007Fڿ\x9C\xB8\u0006\xF0\xFF\xFF\u007F\u0004\xF8\xFF\xFF\u007F\xE5鞜\u0006"
38
+
39
+ deserializer = Odps::ProtobufDeSerializer.new
40
+ deserializer.deserialize(protobufed_str, schema) # => [[1, "apple", #<BigDecimal:7f94dc9b2a80,'0.12E1',18(18)>, 0.5, true, 2016-01-01 10:00:00 +0800], [1000, "red apple", #<BigDecimal:7f94dc9b2648,'0.125E2',18(18)>, 0.9, false, 2016-01-01 10:00:00 +0800]]
30
41
 
31
42
  ## Authors && Contributors
32
43
 
data/lib/odps_protobuf.rb CHANGED
@@ -1,5 +1,23 @@
1
1
  require "odps_protobuf/version"
2
+ require 'odps_protobuf/field'
3
+ require 'odps_protobuf/table'
4
+ require "odps_protobuf/serializer"
5
+ require "odps_protobuf/deserializer"
2
6
 
3
7
  module OdpsProtobuf
4
- # Your code goes here...
8
+ $TUNNEL_META_COUNT = 33_554_430 # magic num 2^25-2
9
+ $TUNNEL_META_CHECKSUM = 33_554_431 # magic num 2^25-1
10
+ $TUNNEL_END_RECORD = 33_553_408 # maigc num 2^25-1024
11
+
12
+ $ODPS_BIGINT = 'bigint'
13
+ $ODPS_DOUBLE = 'double'
14
+ $ODPS_BOOLEAN = 'boolean'
15
+ $ODPS_DATETIME = 'datetime'
16
+ $ODPS_STRING = 'string'
17
+ $ODPS_DECIMAL = 'decimal'
18
+
19
+ $STRING_MAX_LENTH = 8 * 1024 * 1024
20
+ $DATETIME_MAX_TICKS = 253_402_271_999_000
21
+ $DATETIME_MIN_TICKS = -62_135_798_400_000
22
+ $STRING_CHARSET = 'UTF-8'
5
23
  end
@@ -0,0 +1,36 @@
1
+ require 'rbconfig'
2
+
3
+ module OdpsProtobuf
4
+ class CrcCalculator
5
+ # @param [StringIO] data
6
+ # @return crc32c to_i
7
+ def self.calculate(data)
8
+ if !$USE_FAST_CRC
9
+ require_relative 'origin/crc32c'
10
+ crc32c = Digest::CRC32c.new
11
+ crc32c.update(data.string)
12
+ return crc32c.checksum.to_i
13
+ elsif getOsType == 'linux' || getOsType == 'unix'
14
+ require_relative 'lib/odps/linux/crc32c.so'
15
+ return Crc32c.calculate(data.string, data.length, 0).to_i
16
+ elsif getOsType == 'windows'
17
+ require_relative 'lib/odps/win/crc32c.so'
18
+ return Crc32c.calculate(data.string, data.length, 0).to_i
19
+ end
20
+ end
21
+
22
+ def self.getOsType
23
+ host_os = RbConfig::CONFIG['host_os']
24
+ case host_os
25
+ when /mswin|msys|mingw|cygwin|bccwin|wince|emc/
26
+ 'windows'
27
+ when /linux/
28
+ 'linux'
29
+ when /solaris|bsd/
30
+ 'unix'
31
+ else
32
+ fail Error::WebDriverError, 'unspport os'
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,129 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+ require 'digest'
20
+ module Digest
21
+ #
22
+ # Base class for all CRC algorithms.
23
+ #
24
+ class CRC < Digest::Class
25
+ include Digest::Instance
26
+ # The initial value of the CRC checksum
27
+ INIT_CRC = 0x00
28
+ # The XOR mask to apply to the resulting CRC checksum
29
+ XOR_MASK = 0x00
30
+ # The bit width of the CRC checksum
31
+ WIDTH = 0
32
+ #
33
+ # Calculates the CRC checksum.
34
+ #
35
+ # @param [String] data
36
+ # The given data.
37
+ #
38
+ # @return [Integer]
39
+ # The CRC checksum.
40
+ #
41
+ def self.checksum(data)
42
+ crc = new
43
+ crc << data
44
+ crc.checksum
45
+ end
46
+
47
+ #
48
+ # Packs the given CRC checksum.
49
+ #
50
+ # @return [String]
51
+ # The packed CRC checksum.
52
+ #
53
+ def self.pack(_crc)
54
+ ''
55
+ end
56
+
57
+ #
58
+ # Initializes the CRC checksum.
59
+ #
60
+ def initialize
61
+ @crc = self.class.const_get(:INIT_CRC)
62
+ end
63
+
64
+ #
65
+ # The input block length.
66
+ #
67
+ # @return [1]
68
+ #
69
+ def block_length
70
+ 1
71
+ end
72
+
73
+ #
74
+ # The length of the digest.
75
+ #
76
+ # @return [Integer]
77
+ # The length in bytes.
78
+ #
79
+ def digest_length
80
+ (self.class.const_get(:WIDTH) / 8.0).ceil
81
+ end
82
+
83
+ #
84
+ # Updates the CRC checksum with the given data.
85
+ #
86
+ # @param [String] data
87
+ # The data to update the CRC checksum with.
88
+ #
89
+ def update(_data)
90
+ end
91
+
92
+ #
93
+ # @see {#update}
94
+ #
95
+ def <<(data)
96
+ update(data)
97
+ self
98
+ end
99
+
100
+ #
101
+ # Resets the CRC checksum.
102
+ #
103
+ # @return [Integer]
104
+ # The default value of the CRC checksum.
105
+ #
106
+ def reset
107
+ @crc = self.class.const_get(:INIT_CRC)
108
+ end
109
+
110
+ #
111
+ # The resulting CRC checksum.
112
+ #
113
+ # @return [Integer]
114
+ # The resulting CRC checksum.
115
+ #
116
+ def checksum
117
+ @crc ^ self.class.const_get(:XOR_MASK)
118
+ end
119
+
120
+ #
121
+ # Finishes the CRC checksum calculation.
122
+ #
123
+ # @see {pack}
124
+ #
125
+ def finish
126
+ self.class.pack(checksum)
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,126 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+ require_relative 'crc'
20
+ module Digest
21
+ #
22
+ # Implements the CRC32 algorithm.
23
+ #
24
+ class CRC32 < CRC
25
+ WIDTH = 4
26
+ INIT_CRC = 0xffffffff
27
+ XOR_MASK = 0xffffffff
28
+ # Generated by `./pycrc.py --algorithm=table-driven --model=crc-32 --generate=c`
29
+ TABLE = [
30
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
31
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
32
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
33
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
34
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
35
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
36
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
37
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
38
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
39
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
40
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
41
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
42
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
43
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
44
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
45
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
46
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
47
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
48
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
49
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
50
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
51
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
52
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
53
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
54
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
55
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
56
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
57
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
58
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
59
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
60
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
61
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
62
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
63
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
64
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
65
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
66
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
67
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
68
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
69
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
70
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
71
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
72
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
73
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
74
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
75
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
76
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
77
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
78
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
79
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
80
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
81
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
82
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
83
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
84
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
85
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
86
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
87
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
88
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
89
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
90
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
91
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
92
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
93
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
94
+ ]
95
+ #
96
+ # Packs the CRC32 checksum.
97
+ #
98
+ # @param [Integer] crc
99
+ # The checksum to pack.
100
+ #
101
+ # @return [String]
102
+ # The packed checksum.
103
+ #
104
+ def self.pack(crc)
105
+ buffer = ''
106
+ buffer << ((crc & 0xff000000) >> 24).chr
107
+ buffer << ((crc & 0xff0000) >> 16).chr
108
+ buffer << ((crc & 0xff00) >> 8).chr
109
+ buffer << (crc & 0xff).chr
110
+ buffer
111
+ end
112
+
113
+ #
114
+ # Updates the CRC32 checksum.
115
+ #
116
+ # @param [String] data
117
+ # The data to update the checksum with.
118
+ #
119
+ def update(data)
120
+ data.each_byte do |b|
121
+ @crc = (((@crc >> 8) & 0x00ffffff) ^ TABLE[(@crc ^ b) & 0xff])
122
+ end
123
+ self
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,105 @@
1
+ #
2
+ # Licensed to the Apache Software Foundation (ASF) under one
3
+ # or more contributor license agreements. See the NOTICE file
4
+ # distributed with this work for additional information
5
+ # regarding copyright ownership. The ASF licenses this file
6
+ # to you under the Apache License, Version 2.0 (the
7
+ # "License"); you may not use this file except in compliance
8
+ # with the License. You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing,
13
+ # software distributed under the License is distributed on an
14
+ # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ # KIND, either express or implied. See the License for the
16
+ # specific language governing permissions and limitations
17
+ # under the License.
18
+ #
19
+ require_relative 'crc32'
20
+ module Digest
21
+ #
22
+ # Implements the CRC32c algorithm.
23
+ #
24
+ class CRC32c < CRC32
25
+ # Generated by `./pycrc.py --algorithm=table-driven --model=crc-32c --generate=c`
26
+ TABLE = [
27
+ 0x00000000, 0xf26b8303, 0xe13b70f7, 0x1350f3f4,
28
+ 0xc79a971f, 0x35f1141c, 0x26a1e7e8, 0xd4ca64eb,
29
+ 0x8ad958cf, 0x78b2dbcc, 0x6be22838, 0x9989ab3b,
30
+ 0x4d43cfd0, 0xbf284cd3, 0xac78bf27, 0x5e133c24,
31
+ 0x105ec76f, 0xe235446c, 0xf165b798, 0x030e349b,
32
+ 0xd7c45070, 0x25afd373, 0x36ff2087, 0xc494a384,
33
+ 0x9a879fa0, 0x68ec1ca3, 0x7bbcef57, 0x89d76c54,
34
+ 0x5d1d08bf, 0xaf768bbc, 0xbc267848, 0x4e4dfb4b,
35
+ 0x20bd8ede, 0xd2d60ddd, 0xc186fe29, 0x33ed7d2a,
36
+ 0xe72719c1, 0x154c9ac2, 0x061c6936, 0xf477ea35,
37
+ 0xaa64d611, 0x580f5512, 0x4b5fa6e6, 0xb93425e5,
38
+ 0x6dfe410e, 0x9f95c20d, 0x8cc531f9, 0x7eaeb2fa,
39
+ 0x30e349b1, 0xc288cab2, 0xd1d83946, 0x23b3ba45,
40
+ 0xf779deae, 0x05125dad, 0x1642ae59, 0xe4292d5a,
41
+ 0xba3a117e, 0x4851927d, 0x5b016189, 0xa96ae28a,
42
+ 0x7da08661, 0x8fcb0562, 0x9c9bf696, 0x6ef07595,
43
+ 0x417b1dbc, 0xb3109ebf, 0xa0406d4b, 0x522bee48,
44
+ 0x86e18aa3, 0x748a09a0, 0x67dafa54, 0x95b17957,
45
+ 0xcba24573, 0x39c9c670, 0x2a993584, 0xd8f2b687,
46
+ 0x0c38d26c, 0xfe53516f, 0xed03a29b, 0x1f682198,
47
+ 0x5125dad3, 0xa34e59d0, 0xb01eaa24, 0x42752927,
48
+ 0x96bf4dcc, 0x64d4cecf, 0x77843d3b, 0x85efbe38,
49
+ 0xdbfc821c, 0x2997011f, 0x3ac7f2eb, 0xc8ac71e8,
50
+ 0x1c661503, 0xee0d9600, 0xfd5d65f4, 0x0f36e6f7,
51
+ 0x61c69362, 0x93ad1061, 0x80fde395, 0x72966096,
52
+ 0xa65c047d, 0x5437877e, 0x4767748a, 0xb50cf789,
53
+ 0xeb1fcbad, 0x197448ae, 0x0a24bb5a, 0xf84f3859,
54
+ 0x2c855cb2, 0xdeeedfb1, 0xcdbe2c45, 0x3fd5af46,
55
+ 0x7198540d, 0x83f3d70e, 0x90a324fa, 0x62c8a7f9,
56
+ 0xb602c312, 0x44694011, 0x5739b3e5, 0xa55230e6,
57
+ 0xfb410cc2, 0x092a8fc1, 0x1a7a7c35, 0xe811ff36,
58
+ 0x3cdb9bdd, 0xceb018de, 0xdde0eb2a, 0x2f8b6829,
59
+ 0x82f63b78, 0x709db87b, 0x63cd4b8f, 0x91a6c88c,
60
+ 0x456cac67, 0xb7072f64, 0xa457dc90, 0x563c5f93,
61
+ 0x082f63b7, 0xfa44e0b4, 0xe9141340, 0x1b7f9043,
62
+ 0xcfb5f4a8, 0x3dde77ab, 0x2e8e845f, 0xdce5075c,
63
+ 0x92a8fc17, 0x60c37f14, 0x73938ce0, 0x81f80fe3,
64
+ 0x55326b08, 0xa759e80b, 0xb4091bff, 0x466298fc,
65
+ 0x1871a4d8, 0xea1a27db, 0xf94ad42f, 0x0b21572c,
66
+ 0xdfeb33c7, 0x2d80b0c4, 0x3ed04330, 0xccbbc033,
67
+ 0xa24bb5a6, 0x502036a5, 0x4370c551, 0xb11b4652,
68
+ 0x65d122b9, 0x97baa1ba, 0x84ea524e, 0x7681d14d,
69
+ 0x2892ed69, 0xdaf96e6a, 0xc9a99d9e, 0x3bc21e9d,
70
+ 0xef087a76, 0x1d63f975, 0x0e330a81, 0xfc588982,
71
+ 0xb21572c9, 0x407ef1ca, 0x532e023e, 0xa145813d,
72
+ 0x758fe5d6, 0x87e466d5, 0x94b49521, 0x66df1622,
73
+ 0x38cc2a06, 0xcaa7a905, 0xd9f75af1, 0x2b9cd9f2,
74
+ 0xff56bd19, 0x0d3d3e1a, 0x1e6dcdee, 0xec064eed,
75
+ 0xc38d26c4, 0x31e6a5c7, 0x22b65633, 0xd0ddd530,
76
+ 0x0417b1db, 0xf67c32d8, 0xe52cc12c, 0x1747422f,
77
+ 0x49547e0b, 0xbb3ffd08, 0xa86f0efc, 0x5a048dff,
78
+ 0x8ecee914, 0x7ca56a17, 0x6ff599e3, 0x9d9e1ae0,
79
+ 0xd3d3e1ab, 0x21b862a8, 0x32e8915c, 0xc083125f,
80
+ 0x144976b4, 0xe622f5b7, 0xf5720643, 0x07198540,
81
+ 0x590ab964, 0xab613a67, 0xb831c993, 0x4a5a4a90,
82
+ 0x9e902e7b, 0x6cfbad78, 0x7fab5e8c, 0x8dc0dd8f,
83
+ 0xe330a81a, 0x115b2b19, 0x020bd8ed, 0xf0605bee,
84
+ 0x24aa3f05, 0xd6c1bc06, 0xc5914ff2, 0x37faccf1,
85
+ 0x69e9f0d5, 0x9b8273d6, 0x88d28022, 0x7ab90321,
86
+ 0xae7367ca, 0x5c18e4c9, 0x4f48173d, 0xbd23943e,
87
+ 0xf36e6f75, 0x0105ec76, 0x12551f82, 0xe03e9c81,
88
+ 0x34f4f86a, 0xc69f7b69, 0xd5cf889d, 0x27a40b9e,
89
+ 0x79b737ba, 0x8bdcb4b9, 0x988c474d, 0x6ae7c44e,
90
+ 0xbe2da0a5, 0x4c4623a6, 0x5f16d052, 0xad7d5351
91
+ ]
92
+ #
93
+ # Updates the CRC32 checksum.
94
+ #
95
+ # @param [String] data
96
+ # The data to update the checksum with.
97
+ #
98
+ def update(data)
99
+ data.each_byte do |b|
100
+ @crc = (((@crc >> 8) & 0x00ffffff) ^ TABLE[(@crc ^ b) & 0xff])
101
+ end
102
+ self
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,57 @@
1
+ module OdpsProtobuf
2
+ class Deserializer
3
+
4
+ # Deserialize protobufed string into decode data
5
+ #
6
+ # @example
7
+ # protobufed_string = "\b\u0002\u0012\u0005apple\u001A\u00031.2!\u0000\u0000\u0000\u0000\u0000\u0000\xE0?(\u00010\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007F\xCCӥ\xE2\u000F\b\xD0\u000F\u0012\tred apple\u001A\u000412.5!\xCD\xCC\xCC\xCC\xCC\xCC\xEC?(\u00000\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007Fڿ\x9C\xB8\u0006\xF0\xFF\xFF\u007F\u0004\xF8\xFF\xFF\u007F\xE5鞜\u0006"
8
+ # schema = {
9
+ # 'columns' => [
10
+ # { 'name' => 'uuid', 'type' => 'bigint' },
11
+ # { 'name' => 'name', 'type' => 'string' },
12
+ # { 'name' => 'price', 'type' => 'decimal' },
13
+ # { 'name' => 'discount', 'type' => 'double' },
14
+ # { 'name' => 'in_stock', 'type' => 'boolean' },
15
+ # { 'name' => 'created_time', 'type' => 'datetime' }
16
+ # ]
17
+ # }
18
+ # deserialize(protobufed_string, schema) #=> [[1, "apple", #<BigDecimal:7f94dc9b2a80,'0.12E1',18(18)>, 0.5, true, 2016-01-01 10:00:00 +0800], [1000, "red apple", #<BigDecimal:7f94dc9b2648,'0.125E2',18(18)>, 0.9, false, 2016-01-01 10:00:00 +0800]]
19
+ def deserialize(content, schema)
20
+ stream = StringIO.new(content) unless content.is_a?(StringIO)
21
+ schema = OdpsTableSchema.new(schema)
22
+ records = []
23
+ record = []
24
+ until stream.eof?
25
+ key, value = ::Protobuf::Decoder.read_field(stream)
26
+ #p "key: #{key}, value: #{value}"
27
+ if key == $TUNNEL_END_RECORD
28
+ records << record.pop(record.length)
29
+ else
30
+ col = schema.mCols[key - 1]
31
+ break if col.nil?
32
+ case col.mType
33
+ when $ODPS_BIGINT
34
+ record << Sint64Field.decode(value)
35
+ when $ODPS_DOUBLE
36
+ record << DoubleField.decode(value)
37
+ when $ODPS_BOOLEAN
38
+ #p "key: #{key}, value: #{value}, decoded: #{BoolField.decode(value)}"
39
+ record << BoolField.decode(value)
40
+ when $ODPS_DATETIME
41
+ #p "key: #{key}, value: #{value}, decoded: #{DateTimeField.decode(value)}"
42
+ record << DateTimeField.decode(value)
43
+ when $ODPS_STRING
44
+ #p "key: #{key}, value: #{value}, decoded: #{StringField.decode(value)}"
45
+ record << StringField.decode(value)
46
+ when $ODPS_DECIMAL
47
+ #p "key: #{key}, value: #{value}, decoded: #{StringField.decode(value)}"
48
+ record << DecimalField.decode(value)
49
+ else
50
+ fail 'invalid mType'
51
+ end
52
+ end
53
+ end
54
+ records
55
+ end
56
+ end
57
+ end
@@ -0,0 +1 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'field/*.rb')].each { |f| require f }
@@ -0,0 +1,13 @@
1
+ module OdpsProtobuf
2
+ class BoolField
3
+ class << self
4
+ def encode(value)
5
+ [value ? 1 : 0].pack('C')
6
+ end
7
+
8
+ def decode(value)
9
+ value == 1
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module OdpsProtobuf
2
+ class DateTimeField
3
+ class << self
4
+ def encode(value)
5
+ Sint64Field.encode(value)
6
+ end
7
+
8
+ def decode(value)
9
+ Time.at(Sint64Field.decode(value) / 1000)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,15 @@
1
+ module OdpsProtobuf
2
+ class DecimalField
3
+ class << self
4
+
5
+ def encode(value)
6
+ StringField.encode(value)
7
+ end
8
+
9
+ def decode(value)
10
+ BigDecimal.new(StringField.decode(value))
11
+ end
12
+ end
13
+
14
+ end
15
+ end
@@ -0,0 +1,14 @@
1
+ module OdpsProtobuf
2
+ class DoubleField
3
+ class << self
4
+
5
+ def encode(value)
6
+ [value].pack('E')
7
+ end
8
+
9
+ def decode(value)
10
+ value.unpack('E').first
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,13 @@
1
+ module OdpsProtobuf
2
+ class Fixed32Field
3
+ class << self
4
+ def encode(value)
5
+ [value].pack('V')
6
+ end
7
+
8
+ def decode(value)
9
+ value.unpack('V').shift
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,14 @@
1
+ module OdpsProtobuf
2
+ class Fixed64Field
3
+ class << self
4
+ def encode(value)
5
+ [value & 0xffff_ffff, value >> 32].pack('VV')
6
+ end
7
+
8
+ def decode(value)
9
+ unpack_vlaue = value.unpack('VV')
10
+ (unpack_value[1] << 32) ^ unpack_value[0]
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,14 @@
1
+ module OdpsProtobuf
2
+ class FixedStringField
3
+ class << self
4
+
5
+ def encode(value)
6
+ [value].pack('V')
7
+ end
8
+
9
+ def decode(value)
10
+ value.unpack('V').shift
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ module OdpsProtobuf
2
+ class Sint64Field
3
+ class << self
4
+
5
+ def encode(value)
6
+ if value >= 0
7
+ ::Protobuf::Field::VarintField.encode(value << 1)
8
+ else
9
+ ::Protobuf::Field::VarintField.encode(~(value << 1))
10
+ end
11
+ end
12
+
13
+ def decode(value)
14
+ if (value & 1).zero?
15
+ value >> 1 # positive value
16
+ else
17
+ ~value >> 1 # negative value
18
+ end
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -0,0 +1,21 @@
1
+ module OdpsProtobuf
2
+ class StringField
3
+ class << self
4
+
5
+ def encode(value)
6
+ value_to_encode = value.dup
7
+ # value_to_encode.encode!(::Protobuf::Field::StringField::ENCODING, :invalid => :replace, :undef => :replace, :replace => "")
8
+ value_to_encode.force_encoding(::Protobuf::Field::BytesField::BYTES_ENCODING)
9
+ string_bytes = ::Protobuf::Field::VarintField.encode(value_to_encode.size)
10
+ string_bytes << value_to_encode
11
+ end
12
+
13
+ def decode(value)
14
+ bytes_to_decode = value.dup
15
+ bytes_to_decode.force_encoding(::Protobuf::Field::StringField::ENCODING)
16
+ bytes_to_decode
17
+ end
18
+ end
19
+
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ module OdpsProtobuf
2
+ class Uint32Field
3
+ class << self
4
+
5
+ def encode(value)
6
+ return [value].pack('C') if value < 128
7
+ bytes = []
8
+ until value == 0
9
+ bytes << (0x80 | (value & 0x7f))
10
+ value >>= 7
11
+ end
12
+ bytes[-1] &= 0x7f
13
+ bytes.pack('C*')
14
+ end
15
+
16
+ def decode
17
+ end
18
+
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,135 @@
1
+ # encoding: utf-8
2
+
3
+ require 'stringio'
4
+ require 'protobuf'
5
+ require 'odps_protobuf/crc/crc'
6
+
7
+ module OdpsProtobuf
8
+ class Serializer
9
+
10
+ # Serialize fields with schema
11
+ #
12
+ # @example
13
+ # schema = {
14
+ # 'columns' => [
15
+ # { 'name' => 'uuid', 'type' => 'bigint' },
16
+ # { 'name' => 'name', 'type' => 'string' },
17
+ # { 'name' => 'price', 'type' => 'decimal' },
18
+ # { 'name' => 'discount', 'type' => 'double' },
19
+ # { 'name' => 'in_stock', 'type' => 'boolean' },
20
+ # { 'name' => 'created_time', 'type' => 'datetime' }
21
+ # ]
22
+ # }
23
+ # record1 = [1, 'apple', BigDecimal.new("1.2"), 0.5, true, Time.now]
24
+ # record2 = [1000, 'red apple', BigDecimal.new("12.5"), 0.9, false, Time.now]
25
+ #
26
+ # serialize([record1, record2], schema) # => "\b\u0002\u0012\u0005apple\u001A\u00031.2!\u0000\u0000\u0000\u0000\u0000\u0000\xE0?(\u00010\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007F\xCCӥ\xE2\u000F\b\xD0\u000F\u0012\tred apple\u001A\u000412.5!\xCD\xCC\xCC\xCC\xCC\xCC\xEC?(\u00000\x80\xE4ͮ\xBFT\x80\xC0\xFF\u007Fڿ\x9C\xB8\u0006\xF0\xFF\xFF\u007F\u0004\xF8\xFF\xFF\u007F\xE5鞜\u0006"
27
+ def serialize(records, schema)
28
+ schema = OdpsTableSchema.new(schema)
29
+ stream = StringIO.new
30
+ crc32cPack = StringIO.new
31
+
32
+ if records.is_a? Array
33
+ records.each do |record|
34
+ record = covert2record(record, schema) unless record.is_a?(OdpsTableRecord)
35
+
36
+ crc32cRecord = StringIO.new
37
+ schema.mCols.each do |col|
38
+ cellValue = record.getValue(col.mIdx)
39
+ next if cellValue.nil?
40
+ crc32cRecord.write(Fixed32Field.encode(col.mIdx + 1))
41
+ case col.mType
42
+ when $ODPS_BIGINT
43
+ crc32cRecord.write(Fixed64Field.encode(cellValue))
44
+ writeTag(col.mIdx + 1, ::Protobuf::WireType::VARINT, stream)
45
+ stream.write(Sint64Field.encode(cellValue))
46
+ when $ODPS_DOUBLE
47
+ crc32cRecord.write(DoubleField.encode(cellValue))
48
+ writeTag(col.mIdx + 1, ::Protobuf::WireType::FIXED64, stream)
49
+ stream.write(DoubleField.encode(cellValue))
50
+ when $ODPS_BOOLEAN
51
+ crc32cRecord.write(BoolField.encode(cellValue))
52
+ writeTag(col.mIdx + 1, ::Protobuf::WireType::VARINT, stream)
53
+ stream.write(BoolField.encode(cellValue))
54
+ when $ODPS_DATETIME
55
+ crc32cRecord.write(Fixed64Field.encode(cellValue))
56
+ writeTag(col.mIdx + 1, ::Protobuf::WireType::VARINT, stream)
57
+ stream.write(DateTimeField.encode(cellValue))
58
+ when $ODPS_STRING
59
+ crc32cRecord.write(cellValue)
60
+ writeTag(col.mIdx + 1, ::Protobuf::WireType::LENGTH_DELIMITED, stream)
61
+ stream.write(StringField.encode(cellValue))
62
+ when $ODPS_DECIMAL
63
+ crc32cRecord.write(cellValue)
64
+ writeTag(col.mIdx + 1, ::Protobuf::WireType::LENGTH_DELIMITED, stream)
65
+ stream.write(DecimalField.encode(cellValue))
66
+ else
67
+ fail 'invalid mType'
68
+ end
69
+ end
70
+ recordCrc = CrcCalculator.calculate(crc32cRecord)
71
+ #p "TUNNEL_END_RECORD: #{$TUNNEL_END_RECORD}"
72
+ writeTag($TUNNEL_END_RECORD, ::Protobuf::WireType::VARINT, stream)
73
+ stream.write(Uint32Field.encode(recordCrc))
74
+ crc32cPack.write(Fixed32Field.encode(recordCrc))
75
+ end
76
+ #p "TUNNEL_META_COUNT: #{$TUNNEL_META_COUNT}"
77
+ writeTag($TUNNEL_META_COUNT, ::Protobuf::WireType::VARINT, stream)
78
+ stream.write(Sint64Field.encode(records.size))
79
+ #p "TUNNEL_META_CHECKSUM: #{$TUNNEL_META_CHECKSUM}"
80
+ writeTag($TUNNEL_META_CHECKSUM, ::Protobuf::WireType::VARINT, stream)
81
+ stream.write(Uint32Field.encode(CrcCalculator.calculate(crc32cPack)))
82
+ else
83
+ fail 'param must be a array'
84
+ end
85
+
86
+ return stream.string
87
+ end
88
+
89
+ private
90
+
91
+ def writeTag(idx, type, stream)
92
+ key = (idx << 3) | type
93
+ stream << ::Protobuf::Field::VarintField.encode(key)
94
+ end
95
+
96
+ def covert2record(value, schema)
97
+ fail 'value must be a array' unless value.is_a? Array
98
+
99
+ if value.count != schema.getColumnCount
100
+ fail 'column counts are not equal between value and schema'
101
+ end
102
+
103
+ record = OdpsTableRecord.new(schema)
104
+ i = 0
105
+ while i < value.count
106
+ #p schema, schema.getColumnType(i)
107
+ type = schema.getColumnType(i)
108
+ if value[i].nil?
109
+ record.setNullValue(i)
110
+ i += 1
111
+ next
112
+ end
113
+ #p type
114
+ case type
115
+ when $ODPS_BIGINT
116
+ record.setBigInt(i, value[i])
117
+ when $ODPS_BOOLEAN
118
+ record.setBoolean(i, value[i])
119
+ when $ODPS_DATETIME
120
+ record.setDateTime(i, value[i])
121
+ when $ODPS_DOUBLE
122
+ record.setDouble(i, value[i])
123
+ when $ODPS_STRING
124
+ record.setString(i, value[i])
125
+ when $ODPS_DECIMAL
126
+ record.setDecimal(i, value[i])
127
+ else
128
+ fail 'unsupported schema type'
129
+ end
130
+ i += 1
131
+ end
132
+ record
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,155 @@
1
+ module OdpsProtobuf
2
+ class OdpsTableRecord
3
+ attr_reader :mValues, :mSchema
4
+
5
+ def initialize(schema)
6
+ @mSchema = schema
7
+ @mValues = Array.new(@mSchema.getColumnCount)
8
+ end
9
+
10
+ def getColumnsCount
11
+ @mSchema.getColumnCount
12
+ end
13
+
14
+ def getTableSchema
15
+ @mSchema
16
+ end
17
+
18
+ def getValue(idx)
19
+ fail 'idx out of range' if idx < 0 || idx >= @mSchema.getColumnCount
20
+ @mValues.at(idx)
21
+ end
22
+
23
+ def setNullValue(idx)
24
+ setValue(idx, nil)
25
+ end
26
+
27
+ def setBigInt(idx, value)
28
+ if value.is_a? Integer
29
+ setValue(idx, value)
30
+ elsif value.is_a? String
31
+ setValue(idx, value.to_i)
32
+ else
33
+ fail 'value show be Integer, idx:' + idx.to_s + ' value:' + value.to_s
34
+ end
35
+ end
36
+
37
+ def setDouble(idx, value)
38
+ if value.is_a? Float
39
+ setValue(idx, value)
40
+ elsif value.is_a? String
41
+ setValue(idx, value.to_f)
42
+ else
43
+ fail 'value show be Float, idx:' + idx.to_s + ' value:' + value.to_s
44
+ end
45
+ end
46
+
47
+ def setBoolean(idx, value)
48
+ if value.is_a? String
49
+ if value == 'true'
50
+ setValue(idx, true)
51
+ elsif value == 'false'
52
+ setValue(idx, false)
53
+ else
54
+ fail 'value must be true or false, idx:' + idx.to_s + ' value:' + value.to_s
55
+ end
56
+ elsif value != false && value != true
57
+ fail 'value must be bool or string[true,false], idx:' + idx.to_s + ' value:' + value.to_s
58
+ end
59
+ setValue(idx, value)
60
+ end
61
+
62
+ def setDateTime(idx, value)
63
+ if value.is_a?(Integer) && value >= $DATETIME_MIN_TICKS && value <= $DATETIME_MAX_TICKS
64
+ setValue(idx, value)
65
+ elsif value.is_a?(DateTime) || value.is_a?(Time)
66
+ if value.to_i * 1000 >= $DATETIME_MIN_TICKS && value.to_i * 1000 <= $DATETIME_MAX_TICKS
67
+ setValue(idx, value.to_i * 1000)
68
+ else
69
+ fail 'DateTime out of range or value show be Integer and between -62135798400000 and 253402271999000.'
70
+ end
71
+ elsif value.is_a? String
72
+ begin
73
+ tmpTime = Time.parse(value)
74
+ setValue(idx, tmpTime.to_i * 1000)
75
+ rescue
76
+ raise 'Parse string to datetime failed, string:' + value
77
+ end
78
+ else
79
+ fail 'DateTime cell should be in Integer or Time or DateTime format, idx:' + idx.to_s + ' value:' + value.to_s
80
+ end
81
+ end
82
+
83
+ def setDecimal(idx, value)
84
+ if value.is_a? String
85
+ setValue(idx, value)
86
+ elsif value.is_a? Float
87
+ setValue(idx, value.to_s)
88
+ elsif value.is_a? BigDecimal
89
+ setValue(idx, value.to_s)
90
+ else
91
+ fail 'value can not be convert to decimal, idx:' + idx.to_s + ' value:' + value.to_s
92
+ end
93
+ end
94
+
95
+ def setString(idx, value)
96
+ if value.is_a?(String) && value.length < $STRING_MAX_LENTH
97
+ setValue(idx, value)
98
+ else
99
+ fail 'value show be String and len < ' + $STRING_MAX_LENTH.to_s + ', idx:' + idx.to_s + ' value:' + value.to_s
100
+ end
101
+ end
102
+
103
+ private
104
+
105
+ def setValue(idx, value)
106
+ if idx < 0 || idx >= @mSchema.getColumnCount
107
+ fail 'idx out of range, idx:' + idx.to_s + ' value:' + value.to_s
108
+ end
109
+ @mValues[idx] = value
110
+ end
111
+ end
112
+
113
+ $ODPS_BIGINT = 'bigint'
114
+ $ODPS_DOUBLE = 'double'
115
+ $ODPS_BOOLEAN = 'boolean'
116
+ $ODPS_DATETIME = 'datetime'
117
+ $ODPS_STRING = 'string'
118
+ $ODPS_DECIMAL = 'decimal'
119
+
120
+ class OdpsTableColumn
121
+ attr_reader :mName, :mType, :mIdx
122
+ def initialize(name, type, idx)
123
+ @mName = name
124
+ @mType = type
125
+ @mIdx = idx
126
+ end
127
+ end
128
+
129
+ class OdpsTableSchema
130
+ attr_accessor :mCols
131
+ def initialize(jsonobj = nil)
132
+ @mCols = []
133
+ unless jsonobj.nil?
134
+ columns = jsonobj['columns']
135
+ columns.each do |object|
136
+ appendColumn(object['name'], object['type'])
137
+ end
138
+ end
139
+ end
140
+
141
+ def getColumnCount
142
+ @mCols.size
143
+ end
144
+
145
+ def getColumnType(idx)
146
+ fail 'idx out of range' if idx < 0 || idx >= @mCols.size
147
+ @mCols.at(idx).mType
148
+ end
149
+
150
+ def appendColumn(name, type)
151
+ col = OdpsTableColumn.new(name, type, @mCols.size)
152
+ @mCols.push(col)
153
+ end
154
+ end
155
+ end
@@ -1,3 +1,3 @@
1
1
  module OdpsProtobuf
2
- VERSION = "0.1.0"
2
+ VERSION = "0.5.0"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: odps_protobuf
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Newell Zhu
@@ -82,6 +82,26 @@ files:
82
82
  - bin/console
83
83
  - bin/setup
84
84
  - lib/odps_protobuf.rb
85
+ - lib/odps_protobuf/crc/crc.rb
86
+ - lib/odps_protobuf/crc/lib/linux/crc32c.so
87
+ - lib/odps_protobuf/crc/lib/win/crc32c.so
88
+ - lib/odps_protobuf/crc/origin/crc.rb
89
+ - lib/odps_protobuf/crc/origin/crc32.rb
90
+ - lib/odps_protobuf/crc/origin/crc32c.rb
91
+ - lib/odps_protobuf/deserializer.rb
92
+ - lib/odps_protobuf/field.rb
93
+ - lib/odps_protobuf/field/bool_field.rb
94
+ - lib/odps_protobuf/field/datetime_field.rb
95
+ - lib/odps_protobuf/field/decimal_field.rb
96
+ - lib/odps_protobuf/field/double_field.rb
97
+ - lib/odps_protobuf/field/fixed32_field.rb
98
+ - lib/odps_protobuf/field/fixed64_field.rb
99
+ - lib/odps_protobuf/field/fixed_string_field.rb
100
+ - lib/odps_protobuf/field/sint64_field.rb
101
+ - lib/odps_protobuf/field/string_field.rb
102
+ - lib/odps_protobuf/field/uint32_field.rb
103
+ - lib/odps_protobuf/serializer.rb
104
+ - lib/odps_protobuf/table.rb
85
105
  - lib/odps_protobuf/version.rb
86
106
  - odps_protobuf.gemspec
87
107
  homepage: https://github.com/zlx.