digest-xxhash 0.1.0 → 0.1.2

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
  SHA256:
3
- metadata.gz: 155293f54dc37486a7827e7356f3758f0cd411e444a66be7e35058e7f6ed742e
4
- data.tar.gz: 5c304167f2978dec00ed022c985360af16bcd91581f35a280a2c42aa7a4f5555
3
+ metadata.gz: 557c034e51c5ed220c3ebba704e0b6d5dbd415c4178b2fecf4d6adb153cb9562
4
+ data.tar.gz: 209905cf00b851386b306a5a61a8a8a8de42cc7d30159fea4384ffb060cbc114
5
5
  SHA512:
6
- metadata.gz: 510fd4a123c89d68eeb45a263f120dd85e88aa2dca4ca747f4231195dbb1687d77b997a50d3675a2627607f55b22a4134a231c73a7fbf312cef8e6a8676cf846
7
- data.tar.gz: 22dd84864a3bace71d39cd0886d13d74d867b680b6b28fc72d684ff98c169632e1de22758b1063c1514d795caacd019edf6281b480bf78175d8d7ecf7201b099
6
+ metadata.gz: 528a1c15bf7aa8c9aecc9e86c4e953b1fefb6b38b64c64852cffd2dbc254550ef8062f6ebbb5324e6026cc69b4d32f0db2c865a4088dbff1ee1c7c5bf440b511
7
+ data.tar.gz: dec45992be6ff41b92f26ff55e06be1832a115ac2885aa012342cb51643950b35e8a18aaedfb445bd2da7bbaa110d008b5be9b11fbe8fd5f5ed71a87533edda8
data/README.md CHANGED
@@ -1,15 +1,14 @@
1
- # digest-xxhash-ruby
1
+ # digest-xxhash
2
2
 
3
- This gem 'digest-xxhash' provides XXH32 and XXH64 functions for Ruby. It works
4
- on top of Digest::Class and complies with the functional design of
5
- Digest::Instance.
3
+ This gem 'digest-xxhash' provides XXH32 and XXH64 functions for Ruby. It
4
+ inherits Digest::Class and complies with Digest::Instance's functional design.
6
5
 
7
6
  Its core implementation was taken from the official source, which is
8
7
  in https://github.com/Cyan4973/xxHash.
9
8
 
10
9
  ## Installation
11
10
 
12
- Add this line to your application's Gemfile:
11
+ Add this line to the application's Gemfile:
13
12
 
14
13
  gem 'digest-xxhash'
15
14
 
@@ -17,10 +16,21 @@ And then execute:
17
16
 
18
17
  $ bundle
19
18
 
20
- Or install it yourself as:
19
+ It can also be installed manually with:
21
20
 
22
21
  $ gem install digest-xxhash
23
22
 
23
+ The library can also be installed in Gentoo system-wide using 'layman':
24
+
25
+ # Fetch remote list of overlays, and add 'konsolebox' overlay
26
+ layman -f && layman -a konsolebox
27
+
28
+ # Unmask unstable keyword
29
+ echo 'dev-ruby/digest-xxhash' > /etc/portage/package.keywords/dev-ruby.digest-xxhash
30
+
31
+ # Merge package
32
+ emerge dev-ruby/digest-xxhash
33
+
24
34
  ## Example Usage
25
35
 
26
36
  require 'digest/xxhash'
@@ -52,13 +62,23 @@ Or install it yourself as:
52
62
  Digest::XXH64.new.reset("0123456789abcdef").update("12").update("34").hexdigest
53
63
  => "d7544504de216507"
54
64
 
65
+ ## API Documentation
66
+
67
+ RubyGems.org provides autogenerated API documentation of the library in
68
+ https://www.rubydoc.info/gems/digest-xxhash/.
69
+
70
+ ## Homepage
71
+
72
+ https://rubygems.org/gems/digest-xxhash
73
+
55
74
  ## Contributing
56
75
 
57
76
  1. Fork it ( https://github.com/konsolebox/digest-xxhash-ruby/fork ).
58
- 2. Create your feature branch (`git checkout -b my-new-feature`).
59
- 3. Commit your changes (`git commit -am 'Add some feature'`).
77
+ 2. Create feature branch (`git checkout -b my-new-feature`).
78
+ 3. Commit changes (`git commit -am 'Add some feature'`).
60
79
  4. Push to the branch (`git push origin my-new-feature`).
61
80
  5. Create a new Pull Request.
62
81
 
63
82
  [![Build Status](https://travis-ci.org/konsolebox/digest-xxhash-ruby.svg?branch=master)](https://travis-ci.org/konsolebox/digest-xxhash-ruby)
64
- [![Build status](https://ci.appveyor.com/api/projects/status/kb6hvlxjms3ftw7u?svg=true)](https://ci.appveyor.com/project/konsolebox/digest-xxhash-ruby)
83
+ [![Build Status](https://ci.appveyor.com/api/projects/status/kb6hvlxjms3ftw7u?svg=true)](https://ci.appveyor.com/project/konsolebox/digest-xxhash-ruby)
84
+ [![Build Status](https://github.com/konsolebox/digest-xxhash-ruby/actions/workflows/ruby.yml/badge.svg)](https://github.com/konsolebox/digest-xxhash-ruby/actions/workflows/ruby.yml)
@@ -16,7 +16,7 @@ Gem::Specification.new do |spec|
16
16
 
17
17
  spec.required_ruby_version = '>= 2.2'
18
18
 
19
- spec.files = `git ls-files -z`.split("\x0")
19
+ spec.files = `git ls-files -z`.split("\x0").reject{ |f| f =~ /\.yml$/ }
20
20
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
21
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
22
  spec.require_paths = ["lib"]
@@ -67,6 +67,8 @@ static VALUE _Digest_XXHash;
67
67
  static VALUE _Digest_XXH32;
68
68
  static VALUE _Digest_XXH64;
69
69
 
70
+ #define _RSTRING_PTR_UCHAR(x) ((const unsigned char *)RSTRING_PTR(x))
71
+
70
72
  /*
71
73
  * Data types
72
74
  */
@@ -123,10 +125,10 @@ static VALUE _encode_big_endian_32(uint32_t num)
123
125
  temp = num;
124
126
  }
125
127
 
126
- return rb_usascii_str_new((unsigned char *) &temp, sizeof(uint32_t));
128
+ return rb_usascii_str_new((char *) &temp, sizeof(uint32_t));
127
129
  }
128
130
 
129
- static uint32_t _decode_big_endian_32_cstr(unsigned char *str)
131
+ static uint32_t _decode_big_endian_32_cstr(const char *str)
130
132
  {
131
133
  uint32_t temp = read32(str);
132
134
 
@@ -152,10 +154,10 @@ static VALUE _encode_big_endian_64(uint64_t num)
152
154
  temp = num;
153
155
  }
154
156
 
155
- return rb_usascii_str_new((unsigned char *) &temp, sizeof(uint64_t));
157
+ return rb_usascii_str_new((char *) &temp, sizeof(uint64_t));
156
158
  }
157
159
 
158
- static uint64_t _decode_big_endian_64_cstr(unsigned char *str)
160
+ static uint64_t _decode_big_endian_64_cstr(const char *str)
159
161
  {
160
162
  uint64_t temp = read64(str);
161
163
 
@@ -175,7 +177,7 @@ static VALUE _hex_encode_str(VALUE str)
175
177
  {
176
178
  int len = RSTRING_LEN(str);
177
179
  VALUE hex = rb_str_new(0, len * 2);
178
- hex_encode_str_implied(RSTRING_PTR(str), len, RSTRING_PTR(hex));
180
+ hex_encode_str_implied(_RSTRING_PTR_UCHAR(str), len, (unsigned char *)RSTRING_PTR(hex));
179
181
  return hex;
180
182
  }
181
183
 
@@ -221,7 +223,7 @@ static VALUE _Digest_XXHash_ifinish(VALUE self)
221
223
 
222
224
  static VALUE _do_digest(int argc, VALUE* argv, VALUE self, ID finish_method_id)
223
225
  {
224
- VALUE str, seed;
226
+ VALUE str, seed, result;
225
227
  int argc2 = argc > 0 ? rb_scan_args(argc, argv, "02", &str, &seed) : 0;
226
228
 
227
229
  if (argc2 > 0) {
@@ -236,7 +238,7 @@ static VALUE _do_digest(int argc, VALUE* argv, VALUE self, ID finish_method_id)
236
238
  rb_funcall(self, _id_update, 1, str);
237
239
  }
238
240
 
239
- VALUE result = rb_funcall(self, finish_method_id, 0);
241
+ result = rb_funcall(self, finish_method_id, 0);
240
242
 
241
243
  if (argc2 > 0)
242
244
  rb_funcall(self, _id_reset, 0);
@@ -278,7 +280,8 @@ static VALUE _Digest_XXHash_digest(int argc, VALUE* argv, VALUE self)
278
280
  */
279
281
  static VALUE _Digest_XXHash_hexdigest(int argc, VALUE* argv, VALUE self)
280
282
  {
281
- VALUE result = _do_digest(argc, argv, self, _id_finish);
283
+ VALUE result;
284
+ result = _do_digest(argc, argv, self, _id_finish);
282
285
  return _hex_encode_str(result);
283
286
  }
284
287
 
@@ -302,7 +305,8 @@ static VALUE _Digest_XXHash_idigest(int argc, VALUE* argv, VALUE self)
302
305
  */
303
306
  static VALUE _Digest_XXHash_idigest_bang(VALUE self)
304
307
  {
305
- VALUE result = rb_funcall(self, _id_ifinish, 0);
308
+ VALUE result;
309
+ result = rb_funcall(self, _id_ifinish, 0);
306
310
  rb_funcall(self, _id_reset, 0);
307
311
  return result;
308
312
  }
@@ -313,7 +317,7 @@ static VALUE _Digest_XXHash_idigest_bang(VALUE self)
313
317
  * This method is called when instances are cloned. It is responsible for
314
318
  * replicating internal data.
315
319
  */
316
- static VALUE _Digest_XXHash_initialize_copy(VALUE orig)
320
+ static VALUE _Digest_XXHash_initialize_copy(VALUE self, VALUE orig)
317
321
  {
318
322
  rb_raise(rb_eNotImpError, "initialize_copy method not implemented.");
319
323
  }
@@ -325,27 +329,31 @@ static VALUE _Digest_XXHash_initialize_copy(VALUE orig)
325
329
  */
326
330
  static VALUE _Digest_XXHash_inspect(VALUE self)
327
331
  {
328
- VALUE klass = rb_obj_class(self);
329
- VALUE klass_name = rb_class_name(klass);
332
+ VALUE klass, klass_name, hexdigest, args[2];
333
+ klass = rb_obj_class(self);
334
+ klass_name = rb_class_name(klass);
330
335
 
331
336
  if (klass_name == Qnil)
332
337
  klass_name = rb_inspect(klass);
333
338
 
334
- VALUE hexdigest = rb_funcall(self, _id_hexdigest, 0);
339
+ hexdigest = rb_funcall(self, _id_hexdigest, 0);
335
340
 
336
- VALUE args[] = { klass_name, hexdigest };
341
+ args[0] = klass_name;
342
+ args[1] = hexdigest;
337
343
  return rb_str_format(sizeof(args), args, rb_str_new_literal("#<%s|%s>"));
338
344
  }
339
345
 
340
346
  static VALUE _instantiate_and_digest(int argc, VALUE* argv, VALUE klass, ID digest_method_id)
341
347
  {
342
- VALUE str, seed;
343
- int argc2 = rb_scan_args(argc, argv, "11", &str, &seed);
348
+ VALUE str, seed, instance;
349
+ int argc2;
350
+
351
+ argc2 = rb_scan_args(argc, argv, "11", &str, &seed);
344
352
 
345
353
  if (TYPE(str) != T_STRING)
346
354
  rb_raise(rb_eTypeError, "Argument type not string.");
347
355
 
348
- VALUE instance = rb_funcall(klass, _id_new, 0);
356
+ instance = rb_funcall(klass, _id_new, 0);
349
357
 
350
358
  if (argc2 > 1)
351
359
  return rb_funcall(instance, digest_method_id, 2, str, seed);
@@ -453,12 +461,12 @@ static VALUE _Digest_XXH32_reset(int argc, VALUE* argv, VALUE self)
453
461
  if (len == (sizeof(uint32_t) * 2)) {
454
462
  unsigned char hex_decoded_seed[sizeof(uint32_t)];
455
463
 
456
- if (! hex_decode_str_implied(RSTRING_PTR(seed), sizeof(uint32_t) * 2, hex_decoded_seed))
464
+ if (! hex_decode_str_implied(_RSTRING_PTR_UCHAR(seed), sizeof(uint32_t) * 2, hex_decoded_seed))
457
465
  rb_raise(rb_eArgError, "Invalid hex string seed: %s\n", StringValueCStr(seed));
458
466
 
459
- decoded_seed = _decode_big_endian_32_cstr(hex_decoded_seed);
467
+ decoded_seed = _decode_big_endian_32_cstr((const char *)hex_decoded_seed);
460
468
  } else if (len == sizeof(uint32_t)) {
461
- decoded_seed = _decode_big_endian_32_cstr(RSTRING_PTR(seed));
469
+ decoded_seed = _decode_big_endian_32(seed);
462
470
  } else {
463
471
  rb_raise(rb_eArgError, "Invalid seed length. Expecting an 8-character hex string or a 4-byte string.");
464
472
  }
@@ -601,12 +609,12 @@ static VALUE _Digest_XXH64_reset(int argc, VALUE* argv, VALUE self)
601
609
  if (len == (sizeof(uint64_t) * 2)) {
602
610
  unsigned char hex_decoded_seed[sizeof(uint64_t)];
603
611
 
604
- if (! hex_decode_str_implied(RSTRING_PTR(seed), sizeof(uint64_t) * 2, hex_decoded_seed))
612
+ if (! hex_decode_str_implied(_RSTRING_PTR_UCHAR(seed), sizeof(uint64_t) * 2, hex_decoded_seed))
605
613
  rb_raise(rb_eArgError, "Invalid hex string seed: %s\n", StringValueCStr(seed));
606
614
 
607
- decoded_seed = _decode_big_endian_64_cstr(hex_decoded_seed);
615
+ decoded_seed = _decode_big_endian_64_cstr((const char *)hex_decoded_seed);
608
616
  } else if (len == sizeof(uint64_t)) {
609
- decoded_seed = _decode_big_endian_64_cstr(RSTRING_PTR(seed));
617
+ decoded_seed = _decode_big_endian_64(seed);
610
618
  } else {
611
619
  rb_raise(rb_eArgError, "Invalid seed length. Expecting a 16-character hex string or an 8-byte string.");
612
620
  }
@@ -1,2 +1,4 @@
1
1
  require 'mkmf'
2
+ $defs.push('-Wall') if enable_config('all-warnings')
2
3
  create_makefile('digest/xxhash')
4
+ File.write('Makefile', 'V = 1', mode: 'a') if enable_config('verbose-mode')
@@ -69,9 +69,10 @@ static uint64_t read64(const void *ptr)
69
69
  static void hex_encode_str_implied(const unsigned char *src, size_t len, unsigned char *dest)
70
70
  {
71
71
  static const unsigned char table[] = "0123456789abcdef";
72
+ unsigned char c;
72
73
 
73
74
  for (; len > 0; --len) {
74
- unsigned char c = *src++;
75
+ c = *src++;
75
76
  *dest++ = table[c >> 4];
76
77
  *dest++ = table[c & 0x0f];
77
78
  }
@@ -86,8 +87,10 @@ static void hex_encode_str_implied(const unsigned char *src, size_t len, unsigne
86
87
  */
87
88
  static int hex_decode_str_implied(const unsigned char *src, size_t len, unsigned char *dest)
88
89
  {
90
+ unsigned char low, high;
91
+
89
92
  if (len % 2) {
90
- unsigned char low = *src++;
93
+ low = *src++;
91
94
 
92
95
  if (low >= '0' && low <= '9') {
93
96
  low -= '0';
@@ -104,7 +107,7 @@ static int hex_decode_str_implied(const unsigned char *src, size_t len, unsigned
104
107
  }
105
108
 
106
109
  for (; len > 0; len -= 2) {
107
- unsigned char high = *src++;
110
+ high = *src++;
108
111
 
109
112
  if (high >= '0' && high <= '9') {
110
113
  high -= '0';
@@ -116,7 +119,7 @@ static int hex_decode_str_implied(const unsigned char *src, size_t len, unsigned
116
119
  return 0;
117
120
  }
118
121
 
119
- unsigned char low = *src++;
122
+ low = *src++;
120
123
 
121
124
  if (low >= '0' && low <= '9') {
122
125
  low -= '0';
@@ -134,6 +137,7 @@ static int hex_decode_str_implied(const unsigned char *src, size_t len, unsigned
134
137
  return -1;
135
138
  }
136
139
 
140
+ #if 0
137
141
  /*
138
142
  * Calculates length of string that would store decoded hex.
139
143
  */
@@ -147,5 +151,6 @@ static size_t calc_hex_decoded_str_length(size_t hex_encoded_length)
147
151
 
148
152
  return hex_encoded_length / 2;
149
153
  }
154
+ #endif
150
155
 
151
156
  #endif
@@ -2,6 +2,6 @@ require 'digest'
2
2
 
3
3
  module Digest
4
4
  class XXHash < Digest::Class
5
- VERSION = "0.1.0"
5
+ VERSION = "0.1.2"
6
6
  end
7
7
  end
data/test/test.rb CHANGED
@@ -20,38 +20,38 @@ end
20
20
  [Digest::XXH32, Digest::XXH64].each do |klass|
21
21
  describe klass do
22
22
  it "produces correct types of digest outputs" do
23
- klass.digest("").must_be_instance_of String
24
- klass.hexdigest("").must_be_instance_of String
25
- klass.idigest("").must_be_kind_of Integer
26
- klass.new.digest("").must_be_instance_of String
27
- klass.new.hexdigest("").must_be_instance_of String
28
- klass.new.idigest("").must_be_kind_of Integer
23
+ _(klass.digest("")).must_be_instance_of String
24
+ _(klass.hexdigest("")).must_be_instance_of String
25
+ _(klass.idigest("")).must_be_kind_of Integer
26
+ _(klass.new.digest("")).must_be_instance_of String
27
+ _(klass.new.hexdigest("")).must_be_instance_of String
28
+ _(klass.new.idigest("")).must_be_kind_of Integer
29
29
  end
30
30
 
31
31
  it "produces similar output with its digest, hexdigest and idigest methods" do
32
32
  digest = klass.digest("abcd")
33
- klass.new.digest("abcd").must_equal digest
34
- klass.new.update("ab").update("cd").digest.must_equal digest
35
- klass.new.update("ab").update("cd").digest!.must_equal digest
36
- klass.new.reset.update("ab").update("cd").digest!.must_equal digest
33
+ _(klass.new.digest("abcd")).must_equal digest
34
+ _(klass.new.update("ab").update("cd").digest).must_equal digest
35
+ _(klass.new.update("ab").update("cd").digest!).must_equal digest
36
+ _(klass.new.reset.update("ab").update("cd").digest!).must_equal digest
37
37
 
38
38
  hexdigest = klass.hexdigest("abcd")
39
- klass.new.hexdigest("abcd").must_equal hexdigest
40
- klass.new.update("ab").update("cd").hexdigest.must_equal hexdigest
41
- klass.new.update("ab").update("cd").hexdigest!.must_equal hexdigest
42
- klass.new.reset.update("ab").update("cd").hexdigest!.must_equal hexdigest
39
+ _(klass.new.hexdigest("abcd")).must_equal hexdigest
40
+ _(klass.new.update("ab").update("cd").hexdigest).must_equal hexdigest
41
+ _(klass.new.update("ab").update("cd").hexdigest!).must_equal hexdigest
42
+ _(klass.new.reset.update("ab").update("cd").hexdigest!).must_equal hexdigest
43
43
 
44
44
  idigest = klass.idigest("abcd")
45
- klass.new.idigest("abcd").must_equal idigest
46
- klass.new.update("ab").update("cd").idigest.must_equal idigest
47
- klass.new.update("ab").update("cd").idigest!.must_equal idigest
48
- klass.new.reset.update("ab").update("cd").idigest!.must_equal idigest
45
+ _(klass.new.idigest("abcd")).must_equal idigest
46
+ _(klass.new.update("ab").update("cd").idigest).must_equal idigest
47
+ _(klass.new.update("ab").update("cd").idigest!).must_equal idigest
48
+ _(klass.new.reset.update("ab").update("cd").idigest!).must_equal idigest
49
49
 
50
50
  digest_enc = digest.unpack('H*').pop
51
- hexdigest.must_equal digest_enc
51
+ _(hexdigest).must_equal digest_enc
52
52
 
53
53
  idigest_enc = "%08x" % idigest
54
- hexdigest.must_equal idigest_enc
54
+ _(hexdigest).must_equal idigest_enc
55
55
  end
56
56
  end
57
57
  end
@@ -80,7 +80,7 @@ CSV.foreach(File.join(TEST_DIR, 'test.vectors'), col_sep: '|').with_index(1) do
80
80
  describe klass do
81
81
  describe "using #{msg_method}(#{msg_length}) as message generator, and #{seed} as seed" do
82
82
  it "should produce #{sum}" do
83
- klass.hexdigest(msg, seed).must_equal sum
83
+ _(klass.hexdigest(msg, seed)).must_equal sum
84
84
  end
85
85
  end
86
86
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: digest-xxhash
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - konsolebox
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-03-22 00:00:00.000000000 Z
11
+ date: 2021-05-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -60,12 +60,10 @@ extensions:
60
60
  - ext/digest/xxhash/extconf.rb
61
61
  extra_rdoc_files: []
62
62
  files:
63
- - ".travis.yml"
64
63
  - Gemfile
65
64
  - LICENSE
66
65
  - README.md
67
66
  - Rakefile
68
- - appveyor.yml
69
67
  - digest-xxhash.gemspec
70
68
  - ext/digest/xxhash/debug-funcs.h
71
69
  - ext/digest/xxhash/ext.c
@@ -81,7 +79,7 @@ homepage: https://github.com/konsolebox/digest-xxhash-ruby
81
79
  licenses:
82
80
  - MIT
83
81
  metadata: {}
84
- post_install_message:
82
+ post_install_message:
85
83
  rdoc_options: []
86
84
  require_paths:
87
85
  - lib
@@ -96,9 +94,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
94
  - !ruby/object:Gem::Version
97
95
  version: '0'
98
96
  requirements: []
99
- rubyforge_project:
100
- rubygems_version: 2.7.4
101
- signing_key:
97
+ rubygems_version: 3.2.14
98
+ signing_key:
102
99
  specification_version: 4
103
100
  summary: XXHash for Ruby
104
101
  test_files:
data/.travis.yml DELETED
@@ -1,6 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 2.2
4
- - 2.3
5
- - 2.4
6
- - 2.5
data/appveyor.yml DELETED
@@ -1,19 +0,0 @@
1
- version: 1.0.{build}
2
- init:
3
- - cmd: >-
4
- set base_path=C:/Program Files/7-Zip;C:/Program Files/AppVeyor/BuildAgent;C:/Program Files/Git/cmd;C:/Windows/system32;C:/Windows;"C:/Program Files (x86)/GNU/GnuPG/pub"
5
-
6
- set PATH=C:/ruby%ruby_version%/bin;C:/msys64/usr/bin;%base_path%
7
- environment:
8
- matrix:
9
- - ruby_version: 22-x64
10
- - ruby_version: 23-x64
11
- - ruby_version: 24-x64
12
- - ruby_version: 25-x64
13
- install:
14
- - cmd: bundle install
15
- build_script:
16
- - cmd: bundle exec rake -rdevkit compile
17
- test_script:
18
- - cmd: bundle exec rake test
19
- deploy: off