odps_protobuf 0.1.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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.