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.
- data/.document +11 -0
- data/.gitignore +6 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +76 -0
- data/LICENSE +202 -0
- data/NOTICE +4 -0
- data/README.md +375 -0
- data/Rakefile +51 -0
- data/VERSION +1 -0
- data/junkfood.gemspec +147 -0
- data/lib/junkfood/adler32.rb +102 -0
- data/lib/junkfood/adler32_pure.rb +112 -0
- data/lib/junkfood/assert.rb +75 -0
- data/lib/junkfood/base32.rb +198 -0
- data/lib/junkfood/ceb/base_command.rb +62 -0
- data/lib/junkfood/ceb/base_event.rb +42 -0
- data/lib/junkfood/ceb/bus.rb +152 -0
- data/lib/junkfood/ceb/executors/command_executor.rb +44 -0
- data/lib/junkfood/ceb/executors/delayed_job_command_executor.rb +61 -0
- data/lib/junkfood/ceb/executors/event_executor.rb +35 -0
- data/lib/junkfood/ceb/executors.rb +25 -0
- data/lib/junkfood/ceb.rb +27 -0
- data/lib/junkfood/one_time.rb +247 -0
- data/lib/junkfood/paperclip_string_io.rb +66 -0
- data/lib/junkfood/settings.rb +67 -0
- data/lib/junkfood.rb +29 -0
- data/spec/.rspec +1 -0
- data/spec/junkfood/adler32_pure_spec.rb +16 -0
- data/spec/junkfood/adler32_spec.rb +16 -0
- data/spec/junkfood/assert_spec.rb +84 -0
- data/spec/junkfood/base32_spec.rb +39 -0
- data/spec/junkfood/ceb/base_command_spec.rb +73 -0
- data/spec/junkfood/ceb/base_event_spec.rb +67 -0
- data/spec/junkfood/ceb/bus_spec.rb +153 -0
- data/spec/junkfood/ceb/executors/command_executor_spec.rb +24 -0
- data/spec/junkfood/ceb/executors/delayed_job_command_executor_spec.rb +5 -0
- data/spec/junkfood/ceb/executors/event_executor_spec.rb +18 -0
- data/spec/junkfood/one_time_spec.rb +167 -0
- data/spec/junkfood/paperclip_string_io_spec.rb +40 -0
- data/spec/junkfood/settings_spec.rb +7 -0
- data/spec/junkfood_spec.rb +4 -0
- data/spec/spec_helper.rb +20 -0
- 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
|