junkfood 0.1.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.
Files changed (43) hide show
  1. data/.document +11 -0
  2. data/.gitignore +6 -0
  3. data/Gemfile +17 -0
  4. data/Gemfile.lock +76 -0
  5. data/LICENSE +202 -0
  6. data/NOTICE +4 -0
  7. data/README.md +375 -0
  8. data/Rakefile +51 -0
  9. data/VERSION +1 -0
  10. data/junkfood.gemspec +147 -0
  11. data/lib/junkfood/adler32.rb +102 -0
  12. data/lib/junkfood/adler32_pure.rb +112 -0
  13. data/lib/junkfood/assert.rb +75 -0
  14. data/lib/junkfood/base32.rb +198 -0
  15. data/lib/junkfood/ceb/base_command.rb +62 -0
  16. data/lib/junkfood/ceb/base_event.rb +42 -0
  17. data/lib/junkfood/ceb/bus.rb +152 -0
  18. data/lib/junkfood/ceb/executors/command_executor.rb +44 -0
  19. data/lib/junkfood/ceb/executors/delayed_job_command_executor.rb +61 -0
  20. data/lib/junkfood/ceb/executors/event_executor.rb +35 -0
  21. data/lib/junkfood/ceb/executors.rb +25 -0
  22. data/lib/junkfood/ceb.rb +27 -0
  23. data/lib/junkfood/one_time.rb +247 -0
  24. data/lib/junkfood/paperclip_string_io.rb +66 -0
  25. data/lib/junkfood/settings.rb +67 -0
  26. data/lib/junkfood.rb +29 -0
  27. data/spec/.rspec +1 -0
  28. data/spec/junkfood/adler32_pure_spec.rb +16 -0
  29. data/spec/junkfood/adler32_spec.rb +16 -0
  30. data/spec/junkfood/assert_spec.rb +84 -0
  31. data/spec/junkfood/base32_spec.rb +39 -0
  32. data/spec/junkfood/ceb/base_command_spec.rb +73 -0
  33. data/spec/junkfood/ceb/base_event_spec.rb +67 -0
  34. data/spec/junkfood/ceb/bus_spec.rb +153 -0
  35. data/spec/junkfood/ceb/executors/command_executor_spec.rb +24 -0
  36. data/spec/junkfood/ceb/executors/delayed_job_command_executor_spec.rb +5 -0
  37. data/spec/junkfood/ceb/executors/event_executor_spec.rb +18 -0
  38. data/spec/junkfood/one_time_spec.rb +167 -0
  39. data/spec/junkfood/paperclip_string_io_spec.rb +40 -0
  40. data/spec/junkfood/settings_spec.rb +7 -0
  41. data/spec/junkfood_spec.rb +4 -0
  42. data/spec/spec_helper.rb +20 -0
  43. metadata +372 -0
data/README.md ADDED
@@ -0,0 +1,375 @@
1
+ Junkfood
2
+ ========
3
+
4
+ Junkfood is a mesh of different modules and classes that I found useful
5
+ for various projects. I combined them all into this all-in-one library
6
+ because each included component isn't big enough (or comprehensive
7
+ enough) to warrant its own fully managed gem library.
8
+
9
+ Components
10
+ ----------
11
+
12
+ * Adler32
13
+ * Assert
14
+ * Base32
15
+ * CEB - "Command-Event Busing" for Command-Query Responsibility Separation
16
+ * OneTime - HMAC One Time Passwords
17
+ * PaperclipStringIO
18
+ * Settings
19
+
20
+ Adler32
21
+ =======
22
+
23
+ [Adler-32](http://en.wikipedia.org/wiki/Adler-32) is a checksum algorithm
24
+ which was invented by Mark Adler. Compared to a cyclic redundancy check
25
+ of the same length, it trades reliability for speed. Adler-32 is more
26
+ reliable than Fletcher-16, and slightly less reliable than Fletcher-32.
27
+
28
+ Junkfood provides two implementations of Adler-32 in Ruby:
29
+
30
+ * Adler32 uses the Zlib library to do the checksum.
31
+ * Adler32Pure is a pure Ruby implementation of Adler-32 ported
32
+ from the [Pysync library](http://freshmeat.net/projects/pysync/).
33
+
34
+ Example:
35
+
36
+ adler32 = Junkfood::Adler32.new('Wikipedia') # Or Junkfood::Adler32Pure.new
37
+ puts adler32.digest #=> 300286872
38
+
39
+ adler32 = Junkfood::Adler32.new
40
+ digest = adler32.update 'Wikipedia' #=> 300286872
41
+ adler32.digest #=> 300286872
42
+
43
+ Assert
44
+ ======
45
+
46
+ A very simple assertions module to be a drop in "dumb down" replacement
47
+ for the 'wrong' assertion library. It is here just to be my own fallback
48
+ implementation for cases where I may not actually want to install the
49
+ [wrong gem](<http://rubygems.org/gems/wrong>) yet still like that
50
+ style of assertions.
51
+
52
+ require 'junkfood/assert'
53
+ class MyClass
54
+ include Junkfood::Assert
55
+
56
+ def my_method
57
+ testcase = true
58
+ assert { testcase == true } # This will flow through.
59
+ assert { testcase == false } # This will raise an error.
60
+ assert('My Custom Error Message') {
61
+ testcase == false
62
+ }
63
+ rescue Junkfood::Assert::AssertionFailedError => e
64
+ puts e
65
+ end
66
+ end
67
+
68
+ Base32
69
+ ======
70
+
71
+ A ruby implementation of [RFC4648](http://http://tools.ietf.org/html/rfc4648).
72
+ This class requires at least version Ruby 1.9 because it uses the new
73
+ String Encodings internally.
74
+
75
+ require 'junkfood/base32'
76
+
77
+ # Base32 uses StringIO objects by default.
78
+ io = Junkfood::Base32.encode 'MyBinaryStringData'
79
+ puts io.string
80
+ puts io.string.encoding #=> Encoding::ASCII
81
+
82
+ io = Junkfood::Base32.decode 'MyBase32StringData'
83
+ puts io.string
84
+ puts io.string.encoding #=> Encoding::BINARY
85
+
86
+ # The IO can be any object that conforms to Ruby IO.
87
+ # The returned io is the same file passed to output.
88
+ io = Junkfood::Base32.encode 'BinaryData', :output => open('out.b32', 'w')
89
+ io = Junkfood::Base32.decode 'Base32Data', :output => open('out.bin', 'w')
90
+
91
+ # Input is any object that conforms to #each_byte. This includes
92
+ # Strings and File IOs.
93
+ io = Junkfood::Base32.encode(
94
+ open('in.bin', 'r'),
95
+ :output => open('out.b32', 'w'))
96
+ io.close
97
+ io = Junkfood::Base32.decode(
98
+ open('in.b32', 'r'),
99
+ :output => open('out.bin', 'w'))
100
+ io.close
101
+
102
+
103
+ Command Event Busing (CEB)
104
+ ==========================
105
+
106
+ This component is meant to support Command-Query Responsibility Separation.
107
+
108
+ CEB is comprised of three major parts:
109
+
110
+ * The Base Models (BaseCommand, BaseEvent)
111
+ * The Bus (Bus)
112
+ * The Executors (CommandExecutor, EventExecutor)
113
+
114
+ The Base Models implement the foundation of Commands and Events in CQRS;
115
+ the Bus instantiates Command/Event from the parameters, validates
116
+ (using ActiveModel valid?) the Command/Event and drives its process with
117
+ the associated executors; executors (one per Command or Event bus) runs
118
+ the specific process to handle a command or event.
119
+
120
+ Commands are both data representation and handler code for its function.
121
+ Events are just statements of fact about changes in the system.
122
+
123
+ CEB Base Models
124
+ ---------------
125
+
126
+ BaseCommand and BaseEvent uses MongoDb via [mongoid](http://mongoid.org/).
127
+ Command and Event models SHOULD implement the ActiveModel interface; they
128
+ must at least implement the subset of features as described by the
129
+ RSpec tests in base_command_spec.rb and base_event_spec.rb.
130
+
131
+ These base models:
132
+
133
+ 1. Provide persistence for audit logs.
134
+ 2. Provide the base help to represent Commands and Events in our framework.
135
+ Users will subclass BaseCommand and BaseEvent to model their domain.
136
+ 3. Be the "standard contract" for others that want to implement their
137
+ base models. E.g. - Use ActiveRecord instead of Mongoid.
138
+
139
+ Subclasses of BaseCommand that implement their own `perform` method
140
+ SHOULD return the Event (or list of Events) published when said `perform`
141
+ method was executed.
142
+
143
+ CEB Executors
144
+ -------------
145
+
146
+ We implement helpers for the Command Bus and Event Bus part of CQRS.
147
+ So we have two default executors to handle the logic for those two buses.
148
+
149
+ * CommandExecutor
150
+ * EventExecutor
151
+
152
+ CommandExecutor is the default command bus executor that:
153
+
154
+ 1. just calls save! on the instantiated command, raising errors on failure.
155
+ 2. executes the command's perform method (with the assumption that
156
+ the bus validated the command beforehand).
157
+ 3. the return value from `perform` is passed back to the bus send_command
158
+ or send_event call.
159
+
160
+ Alternative CommandExecutors (e.g. - for DelayedJob) may just use its
161
+ own mechanisms to queue up the Command (most likely using the Command's
162
+ to_json serialization) for later execution. In this case, the executor's
163
+ call should return nil or false to the bus. This return value is convention
164
+ to signal this delayed execution to the requester.
165
+
166
+ EventExecutor is the default event bus executor that:
167
+
168
+ 1. just calls save! on the instantiated event, raising errors on failure.
169
+ 2. TODO: publishes the serialized Event (to_json) over a PubSub network such
170
+ as zeromq or webhooks.
171
+
172
+ CEB Example
173
+ -----------
174
+
175
+ class WidgetCreateCommand < Junkfood::Ceb::BaseCommand
176
+
177
+ field :color, :type => String, :default => 'red'
178
+
179
+ def perform
180
+ # Do creation. Update DDD aggregate root, or ActiveRecord State,
181
+ # or whatever is used to keep application state.
182
+ success = true
183
+
184
+ # Now we publish events based on what happened.
185
+ # Normally, there is a one-to-one relation between the number of
186
+ # commands performed to the number of event published.
187
+ if success
188
+ event, result = send_event(
189
+ 'widget_created',
190
+ :command_id => self.id,
191
+ :color => color,
192
+ :other_widget_info => 'to be determined')
193
+ else
194
+ event, result = send_event(
195
+ 'widget_creation_failed',
196
+ :command_id => self.id,
197
+ :error => 'some determined error',
198
+ :other_widget_info => 'to be determined')
199
+ end
200
+
201
+ # This is convention. Commands SHOULD return the event, or list of
202
+ # events, that it published in the execution of this perform method.
203
+ return event
204
+ end
205
+ end
206
+
207
+ class WidgetCreatedEvent < Junkfood::Ceb::BaseEvent
208
+ field :color, :type => String
209
+ field :other_widget_info, :type => String
210
+ end
211
+
212
+ class WidgetCreationFailedEvent < Junkfood::Ceb::BaseEvent
213
+ field :error_info, :type => String
214
+ field :other_widget_info, :type => String
215
+ end
216
+
217
+ class ApplicationController < ActionController::Base
218
+ include Junkfood::Ceb::Bus
219
+ acts_as_command_bus
220
+ end
221
+
222
+ class WidgetController < ApplicationController
223
+ def create
224
+ # params['widget'] is our posted form data that conforms to the Rails
225
+ # way of doing things for ActiveModel. This eliminates hassle for
226
+ # custom parsing, data handling.
227
+
228
+ # Create a command (WidgetCreateCommand) and puts it onto the bus
229
+ # for execution. The command created is returned along with
230
+ # published events by the command.
231
+ command, events = send_command 'widget_create', params['widget']
232
+
233
+ if command.valid?
234
+ # The command is correctly formed, so the backend executors will
235
+ # execute it in the future (or already has executed it).
236
+ end
237
+
238
+ # By convention, Commands SHOULD return the Event, or list of Events,
239
+ # that the command published when its `perform` method was called.
240
+ case result
241
+ when Junkfood::Ceb::BaseEvent
242
+ # The single published event.
243
+ # Can assume that the command was executed.
244
+ when Array
245
+ # An array of Events published.
246
+ # Can assume that the command was executed.
247
+ when nil, false
248
+ # No data was passed back. Nothing can be assumed about the
249
+ # execution of the command.
250
+ end
251
+ end
252
+ end
253
+
254
+ OneTime - HMAC One Time Passwords
255
+ =================================
256
+
257
+ OneTime implements [RFC4226](http://tools.ietf.org/html/rfc4226) and the
258
+ [Time Based](http://tools.ietf.org/html/draft-mraihi-totp-timebased-06)
259
+ version.
260
+
261
+ View the OneTime class docs to see all the options for setting the
262
+ initial counter, time steps, and number of digits each OneTime instance.
263
+
264
+ Example:
265
+
266
+ key = '12345678901234567890'
267
+
268
+ # Using the class methods to get OTP one at a time.
269
+ puts Junkfood::OneTime.hotp(key, 0) #=> 755224
270
+ puts Junkfood::OneTime.hotp(key, 1) #=> 287082
271
+
272
+ # Changing the length of the OTP
273
+ puts Junkfood::OneTime.hotp(key, 0, :digits => 8) #=> 84755224
274
+
275
+ # Using the class methods to get multiple OTP at a time.
276
+ puts Junkfood::OneTime.hotp_multi(key, 0..1) #=> [755224, 287082]
277
+
278
+ # Create a new OTP generator starting at counter 0.
279
+ one_time = Junkfood::OneTime.new key
280
+ # Get an OTP, but don't advance the counter
281
+ puts one_time.otp #=> 755224
282
+ puts one_time.otp #=> 755224
283
+ # Get a range of OTP
284
+ puts one_time.otp :range => 2 #=> [755224, 287082]
285
+
286
+ # Get an OTP, and advance the counter
287
+ puts one_time.otp! #=> 755224
288
+ puts one_time.otp! #=> 287082
289
+ puts one_time.counter #=> 2
290
+ puts one_time.otp! :range => 2 #=> [359152, 969429]
291
+ puts one_time.counter #=> 4
292
+
293
+ # The current Time based OTP for the current epoch step.
294
+ puts one_time.totp
295
+ # A bunch of OTPs preceding and following the current epoch step OTP.
296
+ puts one_time.totp :radius => 2
297
+
298
+ # Setting the length and counter of the OTP on a OneTime instance
299
+ one_time = Junkfood::OneTime.new key, :digits => 8, :counter => 2
300
+ puts one_time.otp! #=> 37359152
301
+ puts one_time.otp! #=> 26969429
302
+
303
+ PaperclipStringIO
304
+ =================
305
+
306
+ This class allows developers to save blobs of in-memory data into
307
+ [paperclip](http://rubygems.org/gems/paperclip) enabled ActiveRecord models
308
+ without requiring the use of temporary files.
309
+
310
+ Example:
311
+
312
+ class FaxDocument < ActiveRecord::Base
313
+ has_attached_file :pdf
314
+ end
315
+
316
+ def incoming_fax_handler()
317
+ attachment = 'Blob of Faxed Data in PDF form'
318
+ fax_number = '555-1234'
319
+
320
+ fax_document = FaxDocument.create(
321
+ :caption => 'Look at this Document!',
322
+ :pdf => PaperclipStringIo.new(
323
+ attachment,
324
+ :filename => "#{fax_number}.pdf",
325
+ :content_type => 'application/pdf'))
326
+ end
327
+
328
+
329
+ Settings
330
+ ========
331
+
332
+ A singleton to allow all parts of a Rails application use the same set
333
+ of settings, loaded from the same settings yaml file.
334
+
335
+ Testing
336
+ =======
337
+ This library uses [Bundler](http://gembundler.com/) for development and testing.
338
+
339
+ > bundle install
340
+ >
341
+ > rake spec
342
+ >
343
+ > rake rcov
344
+
345
+ Note on Patches/Pull Requests
346
+ =============================
347
+ * Fork the project.
348
+ * Make your feature addition or bug fix.
349
+ * Add tests for it. This is important so I don't break it in a
350
+ future version unintentionally.
351
+ * Commit, do not mess with rakefile, version, or history.
352
+ (if you want to have your own version, that is fine but bump version in a
353
+ commit by itself I can ignore when I pull)
354
+ * Send me a pull request. Bonus points for topic branches.
355
+
356
+ Authors
357
+ =======
358
+ * Benjamin Yu - <http://benjaminyu.org/>, <http://github.com/byu>
359
+
360
+ Copyright
361
+ =========
362
+
363
+ > Copyright 2009-2010 Benjamin Yu
364
+ >
365
+ > Licensed under the Apache License, Version 2.0 (the "License");
366
+ > you may not use this file except in compliance with the License.
367
+ > You may obtain a copy of the License at
368
+ >
369
+ > http://www.apache.org/licenses/LICENSE-2.0
370
+ >
371
+ > Unless required by applicable law or agreed to in writing, software
372
+ > distributed under the License is distributed on an "AS IS" BASIS,
373
+ > WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
374
+ > See the License for the specific language governing permissions and
375
+ > limitations under the License.
data/Rakefile ADDED
@@ -0,0 +1,51 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'rake'
11
+
12
+ require 'jeweler'
13
+ Jeweler::Tasks.new do |gem|
14
+ gem.name = "junkfood"
15
+ gem.summary = %Q{My mesh of an all-in-one library for disjoint code.}
16
+ gem.description = %Q{My mesh of an all-in-one library for disjoint code.}
17
+ gem.email = "benjaminlyu@gmail.com"
18
+ gem.homepage = "http://github.com/byu/junkfood"
19
+ gem.authors = ["Benjamin Yu"]
20
+
21
+ gem.extra_rdoc_files << 'LICENSE'
22
+ gem.extra_rdoc_files << 'NOTICE'
23
+ gem.extra_rdoc_files << 'README.md'
24
+
25
+ gem.add_development_dependency "rspec", ">= 2.0.0.beta.19"
26
+ gem.add_development_dependency "yard", "~> 0.6.0"
27
+ gem.add_development_dependency "bundler", "~> 1.0.0"
28
+ gem.add_development_dependency "jeweler", "~> 1.5.0.pre3"
29
+ gem.add_development_dependency "rcov", ">= 0"
30
+
31
+ gem.add_runtime_dependency 'activesupport'
32
+ gem.add_runtime_dependency 'mongoid', '~> 2.0.0.beta.18'
33
+ gem.add_runtime_dependency 'wrong'
34
+ end
35
+ Jeweler::RubygemsDotOrgTasks.new
36
+
37
+ require 'rspec/core'
38
+ require 'rspec/core/rake_task'
39
+ RSpec::Core::RakeTask.new(:spec) do |spec|
40
+ spec.pattern = FileList['spec/**/*_spec.rb']
41
+ end
42
+
43
+ RSpec::Core::RakeTask.new(:rcov) do |spec|
44
+ spec.pattern = 'spec/**/*_spec.rb'
45
+ spec.rcov = true
46
+ end
47
+
48
+ task :default => :spec
49
+
50
+ require 'yard'
51
+ YARD::Rake::YardocTask.new
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/junkfood.gemspec ADDED
@@ -0,0 +1,147 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{junkfood}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Benjamin Yu"]
12
+ s.date = %q{2010-09-30}
13
+ s.description = %q{My mesh of an all-in-one library for disjoint code.}
14
+ s.email = %q{benjaminlyu@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "NOTICE",
18
+ "README.md"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ ".gitignore",
23
+ "Gemfile",
24
+ "Gemfile.lock",
25
+ "LICENSE",
26
+ "NOTICE",
27
+ "README.md",
28
+ "Rakefile",
29
+ "VERSION",
30
+ "junkfood.gemspec",
31
+ "lib/junkfood.rb",
32
+ "lib/junkfood/adler32.rb",
33
+ "lib/junkfood/adler32_pure.rb",
34
+ "lib/junkfood/assert.rb",
35
+ "lib/junkfood/base32.rb",
36
+ "lib/junkfood/ceb.rb",
37
+ "lib/junkfood/ceb/base_command.rb",
38
+ "lib/junkfood/ceb/base_event.rb",
39
+ "lib/junkfood/ceb/bus.rb",
40
+ "lib/junkfood/ceb/executors.rb",
41
+ "lib/junkfood/ceb/executors/command_executor.rb",
42
+ "lib/junkfood/ceb/executors/delayed_job_command_executor.rb",
43
+ "lib/junkfood/ceb/executors/event_executor.rb",
44
+ "lib/junkfood/one_time.rb",
45
+ "lib/junkfood/paperclip_string_io.rb",
46
+ "lib/junkfood/settings.rb",
47
+ "spec/.rspec",
48
+ "spec/junkfood/adler32_pure_spec.rb",
49
+ "spec/junkfood/adler32_spec.rb",
50
+ "spec/junkfood/assert_spec.rb",
51
+ "spec/junkfood/base32_spec.rb",
52
+ "spec/junkfood/ceb/base_command_spec.rb",
53
+ "spec/junkfood/ceb/base_event_spec.rb",
54
+ "spec/junkfood/ceb/bus_spec.rb",
55
+ "spec/junkfood/ceb/executors/command_executor_spec.rb",
56
+ "spec/junkfood/ceb/executors/delayed_job_command_executor_spec.rb",
57
+ "spec/junkfood/ceb/executors/event_executor_spec.rb",
58
+ "spec/junkfood/one_time_spec.rb",
59
+ "spec/junkfood/paperclip_string_io_spec.rb",
60
+ "spec/junkfood/settings_spec.rb",
61
+ "spec/junkfood_spec.rb",
62
+ "spec/spec_helper.rb"
63
+ ]
64
+ s.homepage = %q{http://github.com/byu/junkfood}
65
+ s.require_paths = ["lib"]
66
+ s.rubygems_version = %q{1.3.7}
67
+ s.summary = %q{My mesh of an all-in-one library for disjoint code.}
68
+ s.test_files = [
69
+ "spec/junkfood/adler32_pure_spec.rb",
70
+ "spec/junkfood/adler32_spec.rb",
71
+ "spec/junkfood/assert_spec.rb",
72
+ "spec/junkfood/base32_spec.rb",
73
+ "spec/junkfood/ceb/base_command_spec.rb",
74
+ "spec/junkfood/ceb/base_event_spec.rb",
75
+ "spec/junkfood/ceb/bus_spec.rb",
76
+ "spec/junkfood/ceb/executors/command_executor_spec.rb",
77
+ "spec/junkfood/ceb/executors/delayed_job_command_executor_spec.rb",
78
+ "spec/junkfood/ceb/executors/event_executor_spec.rb",
79
+ "spec/junkfood/one_time_spec.rb",
80
+ "spec/junkfood/paperclip_string_io_spec.rb",
81
+ "spec/junkfood/settings_spec.rb",
82
+ "spec/junkfood_spec.rb",
83
+ "spec/spec_helper.rb"
84
+ ]
85
+
86
+ if s.respond_to? :specification_version then
87
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
88
+ s.specification_version = 3
89
+
90
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
91
+ s.add_development_dependency(%q<bluecloth>, [">= 0"])
92
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
93
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
94
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
95
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
96
+ s.add_development_dependency(%q<rcov>, [">= 0"])
97
+ s.add_development_dependency(%q<activesupport>, [">= 0"])
98
+ s.add_development_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
99
+ s.add_development_dependency(%q<wrong>, [">= 0"])
100
+ s.add_development_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
101
+ s.add_development_dependency(%q<yard>, ["~> 0.6.0"])
102
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
103
+ s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
104
+ s.add_development_dependency(%q<rcov>, [">= 0"])
105
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
106
+ s.add_runtime_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
107
+ s.add_runtime_dependency(%q<wrong>, [">= 0"])
108
+ else
109
+ s.add_dependency(%q<bluecloth>, [">= 0"])
110
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
111
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
112
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
113
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
114
+ s.add_dependency(%q<rcov>, [">= 0"])
115
+ s.add_dependency(%q<activesupport>, [">= 0"])
116
+ s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
117
+ s.add_dependency(%q<wrong>, [">= 0"])
118
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
119
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
120
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
121
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
122
+ s.add_dependency(%q<rcov>, [">= 0"])
123
+ s.add_dependency(%q<activesupport>, [">= 0"])
124
+ s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
125
+ s.add_dependency(%q<wrong>, [">= 0"])
126
+ end
127
+ else
128
+ s.add_dependency(%q<bluecloth>, [">= 0"])
129
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.22"])
130
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
131
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
132
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
133
+ s.add_dependency(%q<rcov>, [">= 0"])
134
+ s.add_dependency(%q<activesupport>, [">= 0"])
135
+ s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
136
+ s.add_dependency(%q<wrong>, [">= 0"])
137
+ s.add_dependency(%q<rspec>, [">= 2.0.0.beta.19"])
138
+ s.add_dependency(%q<yard>, ["~> 0.6.0"])
139
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
140
+ s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre3"])
141
+ s.add_dependency(%q<rcov>, [">= 0"])
142
+ s.add_dependency(%q<activesupport>, [">= 0"])
143
+ s.add_dependency(%q<mongoid>, ["~> 2.0.0.beta.18"])
144
+ s.add_dependency(%q<wrong>, [">= 0"])
145
+ end
146
+ end
147
+
@@ -0,0 +1,102 @@
1
+ # encoding: utf-8
2
+ # Copyright 2009 Benjamin Yu <http://benjaminyu.org/>
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+
16
+ require 'zlib'
17
+
18
+ module Junkfood
19
+
20
+ ##
21
+ # A Ruby implementation of the Adler-32 checksum algorithm,
22
+ # which uses Ruby's own Zlib.adler32 class method.
23
+ #
24
+ # This Ruby implementation is a port of the Python adler32
25
+ # implementation found in the pysync project. The Python reference
26
+ # implementation, itself, was a port from zlib's adler32.c file.
27
+ #
28
+ # @see http://zlib.net/
29
+ # @see http://freshmeat.net/projects/pysync/
30
+ #
31
+ class Adler32
32
+
33
+ # largest prime smaller than 65536
34
+ BASE = 65521
35
+ # largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1
36
+ NMAX = 5552
37
+ # default initial s1 offset
38
+ OFFS = 1
39
+
40
+ ##
41
+ # @param data (String) initial block of data to digest.
42
+ #
43
+ def initialize(data='')
44
+ value = Zlib.adler32(data, OFFS)
45
+ @s2, @s1 = (value >> 16) & 0xffff, value & 0xffff
46
+ @count = data.length
47
+ end
48
+
49
+ ##
50
+ # Adds another block of data to digest.
51
+ #
52
+ # @param data (String) block of data to digest.
53
+ # @return (Fixnum) the updated digest.
54
+ #
55
+ def update(data)
56
+ value = Zlib.adler32(data, (@s2 << 16) | @s1)
57
+ @s2, @s1 = (value >> 16) & 0xffff, value & 0xffff
58
+ @count = @count + data.length
59
+ return self.digest
60
+ end
61
+
62
+ ##
63
+ # @param x1 (Byte)
64
+ # @param xn (Byte)
65
+ # @return (Fixnum) the updated digest.
66
+ #
67
+ def rotate(x1, xn)
68
+ @s1 = (@s1 - x1 + xn) % BASE
69
+ @s2 = (@s2 - (@count * x1) + @s1 - OFFS) % BASE
70
+ return self.digest
71
+ end
72
+
73
+ ##
74
+ # @param b (Byte)
75
+ # @return (Fixnum) the updated digest.
76
+ #
77
+ def rollin(b)
78
+ @s1 = (@s1 + b) % BASE
79
+ @s2 = (@s2 + @s1) % BASE
80
+ @count = @count + 1
81
+ return self.digest
82
+ end
83
+
84
+ ##
85
+ # @param b (Byte)
86
+ # @return (Fixnum) the updated digest.
87
+ #
88
+ def rollout(b)
89
+ @s1 = (@s1 - b) % BASE
90
+ @s2 = (@s2 - @count * b) % BASE
91
+ @count = @count - 1
92
+ return self.digest
93
+ end
94
+
95
+ ##
96
+ # @return (Fixnum) the current Adler32 digest value.
97
+ #
98
+ def digest
99
+ return (@s2 << 16) | @s1
100
+ end
101
+ end
102
+ end